
package com.zdkj.subway.stm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdkj.admin.api.entity.SysDictItem;
import com.zdkj.common.core.constant.CommonConstants;
import com.zdkj.common.core.util.R;
import com.zdkj.common.security.service.PigxUser;
import com.zdkj.common.security.util.ObjectUtils;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.stm.constant.StmConstans;
import com.zdkj.subway.stm.dto.in.CommomConfirmInfoDTO;
import com.zdkj.subway.stm.dto.in.SwStConductorSettleDto;
import com.zdkj.subway.stm.dto.out.SwPmWorkotherDataTypeDTO;
import com.zdkj.subway.stm.dto.out.SwPmWorkotherHappenCauseDTO;
import com.zdkj.subway.stm.dto.out.SwStTicketPettyAddDetailsDto;
import com.zdkj.subway.stm.entity.*;
import com.zdkj.subway.stm.fegin.SupportService;
import com.zdkj.subway.stm.fegin.SystemUserService;
import com.zdkj.subway.stm.mapper.SwStConductorSettleMapper;
import com.zdkj.subway.stm.mapper.SwStMarketingTicketOffineSellMapper;
import com.zdkj.subway.stm.mapper.SwStTicketPettyAddDetailsMapper;
import com.zdkj.subway.stm.mapper.SwStTicketPettyAddMapper;
import com.zdkj.subway.stm.service.*;
import com.zdkj.subway.stm.util.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 售票员结算表（主表）
 *
 * @author chenbo
 * @date 2020-02-01 19:24:00
 */
@Service
@AllArgsConstructor
@Slf4j
public class SwStConductorSettleServiceImpl extends ServiceImpl<SwStConductorSettleMapper, SwStConductorSettle>
        implements SwStConductorSettleService {

    @Autowired
    private SwStConductorSettleDetailService swStConductorSettleDetailService;

    @Resource
    private SwStConductorSettleMapper swStConductorSettleMapper;


    @Autowired
    SwStMarketingTicketGroupSellService ticketGroupSellService;
    @Autowired
    SwStMarketingTicketOffineSellService offineSellService;
    @Autowired
    SwStMarketingTicketOffineTakeTicketService takeTicketService;

    @Autowired
    SwStMarketingTicketService marketingTicketService;

    @Resource
    SwStTicketPettyAddMapper stTicketPettyAddMapper;

    @Autowired
    SwStTicketPettyAddService swStTicketPettyAddService;

    @Autowired
    SwStTicketPettyAddDetailsService swStTicketPettyAddDetailsService;

    @Autowired
    SwStTicketPettyAddCashDetailsService swStTicketPettyAddCashDetailsService;

    @Autowired
    SwStMarketingTicketService swStMarketingTicketService;

    @Resource
    SwStTicketPettyAddDetailsMapper swStTicketPettyAddDetailsMapper;

    @Resource
    SwStMarketingTicketOffineSellMapper swStMarketingTicketOffineSellMapper;

    private final  SwStTicketInformationCheckService swStTicketInformationCheckService;

    @Autowired
    private final SwStInputPassengerWorkService swStInputPassengerWorkService;
    @Autowired
    private final SwStInputPassengerWorkFreeService swStInputPassengerWorkFreeService;
    @Autowired
    private final SwStInputPassengerWorkPayService swStInputPassengerWorkPayService;
    @Autowired
    private final SwStInputPassengerWorkRefundService swStInputPassengerWorkRefundService;
    @Autowired
    private final SwStInputPassengerWorkCashService swStInputPassengerWorkCashService;
    @Autowired
    private final SwStInputPassengerWorkSpecialService swStInputPassengerWorkSpecialService;
    @Autowired
    private final SwStInputPassengerWorkElectronService swStInputPassengerWorkElectronService;
    @Autowired
    private final SwStInputPassengerWorkTicketService swStInputPassengerWorkTicketService;
    @Autowired
    private final SwStInputPassengerWorkOtherService swStInputPassengerWorkOtherService;

    @Autowired
    private final SwStElectronicReceiptService electronicReceiptService;
    @Autowired
    private final SwStElectronicReceiptDetailsService detailsService;

    @Autowired
    private final SystemUserService systemUserService;

    @Autowired
    private final SupportService supportService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveOrUpdateSettleAndDetail(SwStConductorSettleDto swStConductorSettleDto) {
        SwStConductorSettle swStConductorSettle = swStConductorSettleDto.getSwStConductorSettle();
        SwStConductorSettle defaultObj = ObjectUtils.getDefaultObj(SwStConductorSettle.class);
        BeanUtil.copyProperties(defaultObj, swStConductorSettle, CopyOptions.create().setIgnoreNullValue(true));
        //结算时间取系统时间
        swStConductorSettle.setSettleTime(LocalDate.now());
        swStConductorSettleMapper.insert(swStConductorSettle);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeCascadeById(Integer id) {
        //swStConductorSettleDetailService.delByParentId(id);
        swStConductorSettleMapper.deleteById(id);
        return true;
    }

    /**
     * 查找日结算数据详情的时候进行结算 TODO xian弃用
     *
     * @param id
     * @return
     */
    @Override
    public SwStConductorSettleDto getCascadeById(Integer id) {
        /*SwStConductorSettleDto swStConductorSettleDto = new SwStConductorSettleDto();
        SwStTicketPettyAdd swStTicketPettyAdd = getById(id);
        swStConductorSettleDto.setSwStConductorSettle();*/
        SwStConductorSettle swStConductorSettle = swStConductorSettleMapper.selectById(id);
        SwStConductorSettleDto swStConductorSettleDto = new SwStConductorSettleDto();
        swStConductorSettleDto.setSwStConductorSettle(swStConductorSettle);
        String[] jobNos = swStConductorSettle.getConductorJobNo().split(",");
        String[] shifts = swStConductorSettle.getConductorShifts().split(",");
        LocalDate startTime = swStConductorSettle.getWorkingStartTime().toLocalDate();
        //查询营销车票主表Id
        if (jobNos.length == 1) {
            SwStMarketingTicket result = marketingTicketService.getOne(new QueryWrapper<SwStMarketingTicket>().lambda().eq(SwStMarketingTicket::getConductorJobNo, swStConductorSettle.getConductorJobNo())
                    .eq(SwStMarketingTicket::getConductorShifts, swStConductorSettle.getConductorShifts()).eq(SwStMarketingTicket::getOpertorTime, startTime));
            if (null != result) {
                querySellleDetails(result.getId() + "", swStConductorSettleDto);
            }
        } else {
            //1:说明是需要合并的数据
            String[] split = new String[shifts.length];
            for (int i = 0; i < shifts.length; i++) {
                SwStMarketingTicket result = marketingTicketService.getOne(new QueryWrapper<SwStMarketingTicket>().lambda().eq(SwStMarketingTicket::getConductorJobNo, jobNos[i])
                        .eq(SwStMarketingTicket::getConductorShifts, shifts[i]).eq(SwStMarketingTicket::getOpertorTime, startTime));
                if (null != result) {
                    split[i] = result.getId() + "";
                }
            }
            for (String refId : split) {
                if (StringUtils.isEmpty(refId)) {
                    continue;
                }
                List<SwStMarketingTicketGroupSell> ticketGroupSells = ticketGroupSellService.list(new QueryWrapper<SwStMarketingTicketGroupSell>().eq("RELATION_ID", Integer.valueOf(refId)).eq("DEL_FLAG", 0));
                if (CollectionUtil.isNotEmpty(ticketGroupSells)) {
                    List<SwStMarketingTicketGroupSell> groupSells = swStConductorSettleDto.getTicketGroupSells();
                    if (groupSells == null) {
                        swStConductorSettleDto.setTicketGroupSells(ticketGroupSells);
                    } else {
                        Map<String, List<SwStMarketingTicketGroupSell>> ticketMap = groupSells.stream().collect(Collectors.groupingBy(x -> x.getTicketType()));
                        for (SwStMarketingTicketGroupSell ticketGroupSell : ticketGroupSells) {
                            //分组中没有话 进行添加 有的话进行或恶病
                            List<SwStMarketingTicketGroupSell> countList = ticketMap.get(ticketGroupSell.getTicketType());
                            if (countList == null) {
                                List<SwStMarketingTicketGroupSell> addList = new ArrayList<>();
                                addList.add(ticketGroupSell);
                                ticketMap.put(ticketGroupSell.getTicketType(), addList);
                            } else {
                                // 待确认：  到底怎么个合并方法？
                                SwStMarketingTicketGroupSell groupSell = countList.get(0);
                                groupSell.setSellNum(groupSell.getSellNum() + ticketGroupSell.getSellNum());
                                groupSell.setSellAmount(groupSell.getSellAmount().add(ticketGroupSell.getSellAmount()));
                                groupSell.setPayMethod(groupSell.getPayMethod() + "," + ticketGroupSell.getPayMethod());
                                groupSell.setReceiptFilePath(groupSell.getReceiptFilePath() + "," + ticketGroupSell.getReceiptFilePath());
                            }
                        }
                    }
                }
                //2: 线下正常售卖合并
                List<SwStMarketingTicketOffineSell> ticketOffineSellList = offineSellService.list(new QueryWrapper<SwStMarketingTicketOffineSell>().eq("RELATION_ID", Integer.valueOf(refId)).eq("DEL_FLAG", 0));
                if (CollectionUtil.isNotEmpty(ticketOffineSellList)) {
                    List<SwStMarketingTicketOffineSell> groupSells = swStConductorSettleDto.getTicketOffineSells();
                    if (groupSells == null) {
                        swStConductorSettleDto.setTicketOffineSells(ticketOffineSellList);
                    } else {
                        Map<String, List<SwStMarketingTicketOffineSell>> ticketMap = groupSells.stream().collect(Collectors.groupingBy(x -> x.getTicketType()));
                        for (SwStMarketingTicketOffineSell ticketOffineSell : ticketOffineSellList) {
                            //分组中没有话 进行添加 有的话进行或恶病
                            List<SwStMarketingTicketOffineSell> countList = ticketMap.get(ticketOffineSell.getTicketType());
                            if (countList == null) {
                                List<SwStMarketingTicketOffineSell> addList = new ArrayList<>();
                                ticketMap.put(ticketOffineSell.getTicketType(), addList);
                            } else {
                                SwStMarketingTicketOffineSell offineSell = countList.get(0);
                                offineSell.setCashSellAmount(ticketOffineSell.getCashSellAmount().add(offineSell.getCashSellAmount()));
                                offineSell.setCashSellNum(ticketOffineSell.getCashSellNum() + offineSell.getCashSellNum());
                                offineSell.setAlipaySellAmount(ticketOffineSell.getAlipaySellAmount().add(offineSell.getAlipaySellAmount()));
                                offineSell.setAlipaySellNum(ticketOffineSell.getAlipaySellNum() + offineSell.getAlipaySellNum());
                                offineSell.setWechatSellAmount(offineSell.getWechatSellAmount().add(ticketOffineSell.getWechatSellAmount()));
                                offineSell.setWechatSellNum(offineSell.getWechatSellNum() + ticketOffineSell.getWechatSellNum());
                                offineSell.setTotalSellAmount(offineSell.getTotalSellAmount().add(ticketOffineSell.getWechatSellAmount()));
                                offineSell.setTotalSellNum(offineSell.getTotalSellNum() + ticketOffineSell.getTotalSellNum());
                            }
                        }
                    }
                }

                List<SwStMarketingTicketOffineTakeTicket> ticketOffineTakeTickets = takeTicketService.list(new QueryWrapper<SwStMarketingTicketOffineTakeTicket>().eq("RELATION_ID", Integer.valueOf(refId)).eq("DEL_FLAG", 0));
                if (CollectionUtil.isNotEmpty(ticketOffineTakeTickets)) {
                    List<SwStMarketingTicketOffineTakeTicket> groupSells = swStConductorSettleDto.getTicketOffineTakeTickets();
                    if (groupSells == null) {
                        swStConductorSettleDto.setTicketOffineTakeTickets(ticketOffineTakeTickets);
                    } else {
                        Map<String, List<SwStMarketingTicketOffineTakeTicket>> ticketMap = groupSells.stream().collect(Collectors.groupingBy(x -> x.getTicketType()));
                        for (SwStMarketingTicketOffineTakeTicket offineTakeTicket : ticketOffineTakeTickets) {
                            //分组中没有话 进行添加 有的话进行合并
                            List<SwStMarketingTicketOffineTakeTicket> countList = ticketMap.get(offineTakeTicket.getTicketType());
                            if (countList == null) {
                                List<SwStMarketingTicketOffineTakeTicket> addList = new ArrayList<>();
                                addList.add(offineTakeTicket);
                                ticketMap.put(offineTakeTicket.getTicketType(), addList);
                            } else {
                                SwStMarketingTicketOffineTakeTicket takeTicket = countList.get(0);
                                takeTicket.setTicketNum(takeTicket.getTicketNum() + offineTakeTicket.getTicketNum());
                                takeTicket.setSellAmount(takeTicket.getSellAmount().add(offineTakeTicket.getSellAmount()));
                                takeTicket.setReceiptFilePath(takeTicket.getReceiptFilePath() + "," + offineTakeTicket.getReceiptFilePath());
                                takeTicket.setTakeTicketWay(takeTicket.getTakeTicketWay() + "," + offineTakeTicket.getTakeTicketWay());
                                takeTicket.setTicketWayNum(takeTicket.getTicketWayNum() + "," + offineTakeTicket.getTicketWayNum());
                            }
                        }
                    }
                }
            }
        }

        return swStConductorSettleDto;
    }

    private void querySellleDetails(String realtionMarketingId, SwStConductorSettleDto swStConductorSettleDto) {
        List<SwStMarketingTicketGroupSell> ticketGroupSells = ticketGroupSellService.list(new QueryWrapper<SwStMarketingTicketGroupSell>().eq("RELATION_ID", Integer.valueOf(realtionMarketingId)).eq("DEL_FLAG", 0));
        if (CollectionUtil.isNotEmpty(ticketGroupSells)) {
            swStConductorSettleDto.setTicketGroupSells(ticketGroupSells);
        }
        List<SwStMarketingTicketOffineSell> ticketOffineSellList = offineSellService.list(new QueryWrapper<SwStMarketingTicketOffineSell>().eq("RELATION_ID", Integer.valueOf(realtionMarketingId)).eq("DEL_FLAG", 0));
        if (CollectionUtil.isNotEmpty(ticketOffineSellList)) {
            swStConductorSettleDto.setTicketOffineSells(ticketOffineSellList);
        }
        List<SwStMarketingTicketOffineTakeTicket> ticketOffineTakeTickets = takeTicketService.list(new QueryWrapper<SwStMarketingTicketOffineTakeTicket>().eq("RELATION_ID", Integer.valueOf(realtionMarketingId)).eq("DEL_FLAG", 0));
        if (CollectionUtil.isNotEmpty(ticketOffineTakeTickets)) {
            swStConductorSettleDto.setTicketOffineTakeTickets(ticketOffineTakeTickets);
        }
    }

    @Override
    @Transactional
    public boolean updateSettleDetail(SwStConductorSettleDto swStConductorSettleDto) {
        //只能更新主表 不能更新从表
        SwStConductorSettle swStConductorSettle = swStConductorSettleDto.getSwStConductorSettle();
        updateById(swStConductorSettle);
        return true;
    }

    /**
     * 合并数据  主表和从表都需要合并 注意
     * 新的合并方案
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional
    public boolean mergeSellData(List<Integer> ids,String conductorShifts, Boolean isFlag) {
        //conductorShifts = "08:00:00-10:00:00";

        String [] submit = {"0"};
        if(isFlag){//是审核的
            submit = new String[]{"0", "1"};
        }
        List<String> unSubmit = Arrays.asList(submit);
        // TODO 合并售票员日结算
        SwStConductorSettle mergeData = null;
        List<SwStConductorSettle> mergeDatList = list(new QueryWrapper<SwStConductorSettle>().lambda()
                .in(SwStConductorSettle::getId, ids)
                .in(SwStConductorSettle::getApprovalStatus, unSubmit)
                .eq(SwStConductorSettle::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStConductorSettle::getDelFlag,"0"));
        if (mergeDatList.size() < 2) {
            return false;
        }
        //校验必须是一天的数据 并且是相同的设备操作号才能合并
        String deviceOperateNum = mergeDatList.get(0).getDeviceOperateNum();
        LocalDate localDate = mergeDatList.get(0).getWorkingStartTime().toLocalDate();
        for (SwStConductorSettle settle : mergeDatList) {
            if (!settle.getWorkingStartTime().toLocalDate().equals(localDate)) {
                return false;
            }
            if (!settle.getDeviceOperateNum().equals(deviceOperateNum)) {
                return false;
            }
        }

        for (Integer id : ids) {
            //合并数据
            SwStConductorSettle settle = getById(id);
            if (mergeData == null) {
                mergeData = settle;
            } else {
                if (mergeData.getConductorJobNo() != null) {
                    compareJobNoTrunReplace(mergeData, settle);//工号/名字替换排序
                }
                mergeData.setConductorId(mergeData.getConductorId() + "," + settle.getConductorId());
                mergeData.setMorningAndEveningShifts(mergeData.getMorningAndEveningShifts() + "," + settle.getMorningAndEveningShifts());
                mergeData.setAdanceAmount(mergeData.getAdanceAmount().add(settle.getAdanceAmount()));
                mergeData.setRealAmount(mergeData.getRealAmount().add(settle.getRealAmount()));
                String bom = distinctBom(mergeData.getBomCode(), settle.getBomCode());
                mergeData.setBomCode(BeanUtilsStm.bomOrJobNoSort(bom));//结账单合并时BOM编号去重排序
                //mergeData.setRealtionMarketingId(mergeData.getRealtionMarketingId() + "," + settle.getRealtionMarketingId());

                mergeData.setMergeConductorShifts(mergeData.getConductorShifts() + "," + settle.getConductorShifts());//被合并的班次
                mergeData.setConductorShifts(conductorShifts);//班次为可选择的
                mergeData.setIsMerge("1");//是合并数据
                mergeData.setGuardTime(settle.getGuardTime());
				mergeData.setIsBeMergedId(mergeData.getId() + "," + settle.getId());//被合并的数据ID

            }

        }
        //逻辑删除主表
        swStConductorSettleMapper.deleteBatchIds(mergeDatList.stream().map(SwStConductorSettle::getId).collect(Collectors.toList()));
        //保存主表
        save(mergeData);
        if(isFlag){
            mergeData.setLineCode(mergeDatList.get(0).getLineCode());
            mergeData.setStationCode(mergeDatList.get(0).getStationCode());
            mergeData.setApprovalStatus(CommonConstants.UN_SUBMIT);
            updateById(mergeData);
        }

        // TODO 合并乘客事务数据录入  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次
        boolean passgaerMerge = inputPassagerWorkMergeData(mergeData,unSubmit,isFlag);

        // TODO 合并其他相关数据录入  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次
        boolean otherpassgaerMerge = otherPassagerWorkMergeData(mergeData,unSubmit,isFlag);

        // TODO 合并乘客事务退换票  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次
        boolean ticketpassgaerMerge = ticketPassagerWorkMergeData(mergeData,unSubmit,isFlag);

        // TODO 合并配票与配备用金  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次
        boolean ticketPettyAddMerge = ticketPettyAddMergeData(mergeData,unSubmit,isFlag);

        // TODO 合并营销车票  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次
        boolean marketingTicketMerge = marketingTicketMergeData(mergeData,unSubmit,isFlag);

        return true;
    }


    /**
     * 乘客事务录入合并
     * @param mergeData
     * @param unSubmit
     * @param isFlag
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean inputPassagerWorkMergeData(SwStConductorSettle mergeData, List<String> unSubmit, Boolean isFlag) {
        // TODO 合并乘客事务数据录入  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次，日期
        LocalDate settleTime = mergeData.getSettleTime();//结算日期
        String conductorJobNo = mergeData.getConductorJobNo();//工号
        String conductorName = mergeData.getConductorName();//售票员名字
        String deviceOperateNum = mergeData.getDeviceOperateNum();//设备操作号
        String conductorShifts = mergeData.getConductorShifts();//班次
        String mergeConductorShifts = mergeData.getMergeConductorShifts();//合并班次
        String lineCode = mergeData.getLineCode();
        String stationCode = mergeData.getStationCode();
        List<SwStInputPassengerWork> mergeDatList = swStInputPassengerWorkService.list(new QueryWrapper<SwStInputPassengerWork>().lambda()
                .in(SwStInputPassengerWork::getConductorCode, conductorJobNo.split(","))
                .in(SwStInputPassengerWork::getClassNumber, mergeConductorShifts.split(","))
                .eq(SwStInputPassengerWork::getWorkDate, settleTime)
                .eq(SwStInputPassengerWork::getLineCode, lineCode)
                .eq(SwStInputPassengerWork::getStationCode, stationCode)
                .eq(SwStInputPassengerWork::getDeviceOperateNum, deviceOperateNum)
                .in(SwStInputPassengerWork::getSubmitStatus, unSubmit)
                .eq(SwStInputPassengerWork::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStInputPassengerWork::getDelFlag,"0"));
        if (CollectionUtils.isEmpty(mergeDatList)) {
            return false;
        }
        SwStInputPassengerWork passengerWorkMergeData = mergeDatList.get(0);//乘客事务数据录入主表

        //故障退款
        List<SwStInputPassengerWorkRefund> firstRefundList = swStInputPassengerWorkRefundService.getBaseMapper().selectList(
                Wrappers.<SwStInputPassengerWorkRefund>lambdaQuery()
                        .eq(SwStInputPassengerWorkRefund::getRelationId, passengerWorkMergeData.getId())
        );
        //付费出站发售
        List<SwStInputPassengerWorkPay> firstPayList = swStInputPassengerWorkPayService.getBaseMapper().selectList(
                Wrappers.<SwStInputPassengerWorkPay>lambdaQuery()
                        .eq(SwStInputPassengerWorkPay::getRelationId, passengerWorkMergeData.getId())
        );
        //现金事务
        List<SwStInputPassengerWorkCash> firstCashList = swStInputPassengerWorkCashService.getBaseMapper().selectList(
                Wrappers.<SwStInputPassengerWorkCash>lambdaQuery()
                        .eq(SwStInputPassengerWorkCash::getRelationId, passengerWorkMergeData.getId())
        );
        //电子事务
        List<SwStInputPassengerWorkElectron> firstElectronList = swStInputPassengerWorkElectronService.getBaseMapper().selectList(
                Wrappers.<SwStInputPassengerWorkElectron>lambdaQuery()
                        .eq(SwStInputPassengerWorkElectron::getRelationId, passengerWorkMergeData.getId())
        );
        //特殊车票发售
        SwStInputPassengerWorkSpecial firstSpecialOne = swStInputPassengerWorkSpecialService.getBaseMapper().selectOne(
                Wrappers.<SwStInputPassengerWorkSpecial>lambdaQuery()
                        .eq(SwStInputPassengerWorkSpecial::getRelationId, passengerWorkMergeData.getId())
        );
        SwStInputPassengerWorkSpecial specialOneLast = null;
        //免费车票发售
        SwStInputPassengerWorkFree firstFreeOne = swStInputPassengerWorkFreeService.getBaseMapper().selectOne(
                Wrappers.<SwStInputPassengerWorkFree>lambdaQuery()
                        .eq(SwStInputPassengerWorkFree::getRelationId, passengerWorkMergeData.getId())
        );
        SwStInputPassengerWorkFree freeOneLast = null;
        if(mergeDatList.size() == 2){
            SwStInputPassengerWork swStInputPassengerWork = mergeDatList.get(1);
            passengerWorkMergeData.setConductorName(conductorName);
            passengerWorkMergeData.setConductorCode(conductorJobNo);
            String bom = distinctBom(passengerWorkMergeData.getBomCode(),swStInputPassengerWork.getBomCode());
            passengerWorkMergeData.setBomCode(BeanUtilsStm.bomOrJobNoSort(bom));// TODO bom公共方法去重排序
            passengerWorkMergeData.setIsMerge("1");//是合并数据
            passengerWorkMergeData.setIsBeMergedId(passengerWorkMergeData.getId() + "," + swStInputPassengerWork.getId());//被合并的数据ID
            passengerWorkMergeData.setMergeConductorShifts(mergeConductorShifts);//被合并的班次
            passengerWorkMergeData.setClassNumber(conductorShifts);//班次为可选择的

            //合并故障退款
            List<SwStInputPassengerWorkRefund> lastRefundList = swStInputPassengerWorkRefundService.getBaseMapper().selectList(
                    Wrappers.<SwStInputPassengerWorkRefund>lambdaQuery()
                            .eq(SwStInputPassengerWorkRefund::getRelationId, swStInputPassengerWork.getId())
            );
            if(CollectionUtils.isNotEmpty(lastRefundList)){
                firstRefundList.addAll(lastRefundList);
            }

            //合并付费出站发售
            List<SwStInputPassengerWorkPay> lastPayList = swStInputPassengerWorkPayService.getBaseMapper().selectList(
                    Wrappers.<SwStInputPassengerWorkPay>lambdaQuery()
                            .eq(SwStInputPassengerWorkPay::getRelationId, swStInputPassengerWork.getId())
            );
            if(CollectionUtils.isNotEmpty(lastPayList)){
                firstPayList.addAll(lastPayList);
            }

            //合并现金事务
            List<SwStInputPassengerWorkCash> lastCashList = swStInputPassengerWorkCashService.getBaseMapper().selectList(
                    Wrappers.<SwStInputPassengerWorkCash>lambdaQuery()
                            .eq(SwStInputPassengerWorkCash::getRelationId, swStInputPassengerWork.getId())
            );
            if(CollectionUtils.isNotEmpty(lastCashList)){
                firstCashList.addAll(lastCashList);
            }

            //合并电子事务
            List<SwStInputPassengerWorkElectron> lastElectronList = swStInputPassengerWorkElectronService.getBaseMapper().selectList(
                    Wrappers.<SwStInputPassengerWorkElectron>lambdaQuery()
                            .eq(SwStInputPassengerWorkElectron::getRelationId, swStInputPassengerWork.getId())
            );
            if(CollectionUtils.isNotEmpty(lastElectronList)){
                firstElectronList.addAll(lastElectronList);
            }

            //合并特殊车票发售
            SwStInputPassengerWorkSpecial lastSpecialOne = swStInputPassengerWorkSpecialService.getBaseMapper().selectOne(
                    Wrappers.<SwStInputPassengerWorkSpecial>lambdaQuery()
                            .eq(SwStInputPassengerWorkSpecial::getRelationId, swStInputPassengerWork.getId())
            );
            if(ObjectUtil.isNotEmpty(firstSpecialOne) && ObjectUtil.isNotEmpty(lastSpecialOne)){
                //2021-06-01特殊发售新增字段 f1-f5 张数
                firstSpecialOne.setF1(firstSpecialOne.getF1()+lastSpecialOne.getF1());
                firstSpecialOne.setF2(firstSpecialOne.getF2()+lastSpecialOne.getF2());
                firstSpecialOne.setF3(firstSpecialOne.getF3()+lastSpecialOne.getF3());
                firstSpecialOne.setF4(firstSpecialOne.getF4()+lastSpecialOne.getF4());
                firstSpecialOne.setF5(firstSpecialOne.getF5()+lastSpecialOne.getF5());
                firstSpecialOne.setSoliderNumber(firstSpecialOne.getSoliderNumber()+lastSpecialOne.getSoliderNumber());
                firstSpecialOne.setOtherNumber(firstSpecialOne.getOtherNumber()+lastSpecialOne.getOtherNumber());
                firstSpecialOne.setSellNumber(firstSpecialOne.getSoliderNumber()+firstSpecialOne.getOtherNumber()+firstSpecialOne.getF1()+firstSpecialOne.getF2()+firstSpecialOne.getF3()+firstSpecialOne.getF4()+firstSpecialOne.getF5());
            }else if(ObjectUtil.isEmpty(firstSpecialOne) && ObjectUtil.isNotEmpty(lastSpecialOne)){
                specialOneLast = lastSpecialOne;
            }

            //合并免费车票发售
            SwStInputPassengerWorkFree lastFreeOne = swStInputPassengerWorkFreeService.getBaseMapper().selectOne(
                    Wrappers.<SwStInputPassengerWorkFree>lambdaQuery()
                            .eq(SwStInputPassengerWorkFree::getRelationId, swStInputPassengerWork.getId())
            );
            if(ObjectUtil.isNotEmpty(firstFreeOne) && ObjectUtil.isNotEmpty(lastFreeOne)){
                firstFreeOne.setGateMisuseNumber(firstFreeOne.getGateMisuseNumber()+lastFreeOne.getGateMisuseNumber());
				firstFreeOne.setMobileNoeleNumber(firstFreeOne.getMobileNoeleNumber()+lastFreeOne.getMobileNoeleNumber());
                firstFreeOne.setTicketDamageNumber(firstFreeOne.getTicketDamageNumber()+lastFreeOne.getTicketDamageNumber());
                firstFreeOne.setOtherNumber(firstFreeOne.getOtherNumber()+lastFreeOne.getOtherNumber());
                firstFreeOne.setTotal(firstFreeOne.getGateMisuseNumber()+firstFreeOne.getMobileNoeleNumber()+firstFreeOne.getTicketDamageNumber()+firstFreeOne.getOtherNumber());
            }else if(ObjectUtil.isEmpty(firstFreeOne) && ObjectUtil.isNotEmpty(lastFreeOne)){
                freeOneLast = lastFreeOne;
            }

        }else {//you一条记录也算合并的
            passengerWorkMergeData.setConductorName(conductorName);
            passengerWorkMergeData.setConductorCode(conductorJobNo);
            passengerWorkMergeData.setBomCode(BeanUtilsStm.bomOrJobNoSort(mergeData.getBomCode()));// TODO bom公共方法排序
            passengerWorkMergeData.setIsMerge("1");//是合并数据
            passengerWorkMergeData.setIsBeMergedId(passengerWorkMergeData.getId().toString());//被合并的数据ID
            passengerWorkMergeData.setMergeConductorShifts(passengerWorkMergeData.getClassNumber());//被合并的班次
            passengerWorkMergeData.setClassNumber(conductorShifts);//班次为可选择的

        }

        //乘客事务数据录入删除和合并
        List<Integer> idList = mergeDatList.stream().map(SwStInputPassengerWork::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            swStInputPassengerWorkService.removeByIds(idList);
        }
        swStInputPassengerWorkService.save(passengerWorkMergeData);
        if(isFlag){
            passengerWorkMergeData.setLineCode(lineCode);
            passengerWorkMergeData.setStationCode(stationCode);
            passengerWorkMergeData.setSubmitStatus(CommonConstants.UN_SUBMIT);
            swStInputPassengerWorkService.updateById(passengerWorkMergeData);
        }
        int mainNewId = passengerWorkMergeData.getId();//获取合并后的mainId

        //故障退款新增合并后数据
        if(CollectionUtils.isNotEmpty(firstRefundList)){
            firstRefundList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            swStInputPassengerWorkRefundService.saveBatch(firstRefundList);
        }

        //付费出站发售新增合并后数据
        if(CollectionUtils.isNotEmpty(firstPayList)){
            firstPayList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            swStInputPassengerWorkPayService.saveBatch(firstPayList);
        }

        //现金事务新增合并后数据
        if(CollectionUtils.isNotEmpty(firstCashList)){
            firstCashList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            swStInputPassengerWorkCashService.saveBatch(firstCashList);
        }

        //电子事务新增合并后数据
        if(CollectionUtils.isNotEmpty(firstElectronList)){
            firstElectronList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            swStInputPassengerWorkElectronService.saveBatch(firstElectronList);
        }

        //特殊车票发售新增合并后数据
        if(ObjectUtil.isNotEmpty(firstSpecialOne)){
            firstSpecialOne.setId(null);
            firstSpecialOne.setRelationId(mainNewId);
            swStInputPassengerWorkSpecialService.save(firstSpecialOne);
        }
        if(ObjectUtil.isNotEmpty(specialOneLast)){
            specialOneLast.setId(null);
            specialOneLast.setRelationId(mainNewId);
            swStInputPassengerWorkSpecialService.save(specialOneLast);
        }

        //免费车票发售新增合并后数据
        if(ObjectUtil.isNotEmpty(firstFreeOne)){
            firstFreeOne.setId(null);
            firstFreeOne.setRelationId(mainNewId);
            swStInputPassengerWorkFreeService.save(firstFreeOne);
        }
        if(ObjectUtil.isNotEmpty(freeOneLast)){
            freeOneLast.setId(null);
            freeOneLast.setRelationId(mainNewId);
            swStInputPassengerWorkFreeService.save(freeOneLast);
        }
        return true;
    }


    /**
     * 其他相关数据录入合并
     * @param mergeData
     * @param unSubmit
     * @param isFlag
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean otherPassagerWorkMergeData(SwStConductorSettle mergeData, List<String> unSubmit, Boolean isFlag) {
        // TODO 合并其他相关数据录入  根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次，日期
        LocalDate settleTime = mergeData.getSettleTime();//结算日期
        String conductorJobNo = mergeData.getConductorJobNo();//工号
        String conductorName = mergeData.getConductorName();//售票员名字
        String deviceOperateNum = mergeData.getDeviceOperateNum();//设备操作号
        String conductorShifts = mergeData.getConductorShifts();//班次
        String mergeConductorShifts = mergeData.getMergeConductorShifts();//合并班次
        String lineCode = mergeData.getLineCode();
        String stationCode = mergeData.getStationCode();
        List<SwStInputPassengerWorkOther> mergeDatList = swStInputPassengerWorkOtherService.list(new QueryWrapper<SwStInputPassengerWorkOther>()
                .eq("DATE_FORMAT(INPUT_TIME, '%Y-%m-%d')",settleTime)
                .in("CONDUCTOR_CODE", conductorJobNo.split(","))
                .in("CLASS_NUMBER", mergeConductorShifts.split(","))
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("DEVICE_OPERATE_NUM", deviceOperateNum)
                .in("SUBMIT_STATUS", unSubmit)
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));

        if (CollectionUtils.isEmpty(mergeDatList)) {
            return false;
        }
//        SwStInputPassengerWork swStInputPassengerWork = mergeDatList.get(1);

        // TODO 按故障运营商、数据类型、产生原因保持一致合并
        // 分组统计
        Map<String,List<SwStInputPassengerWorkOther>> countMap = mergeDatList.stream().collect(Collectors
                .groupingBy(o -> o.getFailureOperator() + "_" + o.getDataType() + "_" + o.getHappenCause(), Collectors.toList()));

        if(countMap.isEmpty()){
            return false;
        }
        Set<String> keySet = countMap.keySet();
        List<SwStInputPassengerWorkOther> mergeList = new ArrayList<>();
        List<SwStInputPassengerWorkOther> removeList = new ArrayList<>();
        for (String key : keySet) {
            List<SwStInputPassengerWorkOther> swStInputPassengerWorkOthers = countMap.get(key);
            if(CollectionUtils.isNotEmpty(swStInputPassengerWorkOthers)){
                int sum = swStInputPassengerWorkOthers.stream().mapToInt(SwStInputPassengerWorkOther::getTicketNumber).sum();
                BigDecimal amount = swStInputPassengerWorkOthers.stream()
                        // 将对象的mongey取出来map为Bigdecimal
                        .map(SwStInputPassengerWorkOther::getAmount)
                        // 使用reduce聚合函数,实现累加器
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                SwStInputPassengerWorkOther otherMerge = swStInputPassengerWorkOthers.get(0);
                otherMerge.setTicketNumber(sum);
                otherMerge.setAmount(amount);
                otherMerge.setConductorName(conductorName);
                otherMerge.setConductorCode(conductorJobNo);
                otherMerge.setIsMerge("1");//是合并数据
                List<Integer> ids = swStInputPassengerWorkOthers.stream().map(SwStInputPassengerWorkOther::getId).collect(Collectors.toList());
                otherMerge.setIsBeMergedId(StringUtils.join(ids,","));//被合并的数据ID
                otherMerge.setMergeConductorShifts(mergeConductorShifts);//被合并的班次
                otherMerge.setClassNumber(conductorShifts);//班次为可选择的

                mergeList.add(otherMerge);
                removeList.addAll(swStInputPassengerWorkOthers);
            }
        }
        //批量逻辑删除
        List<Integer> idList = removeList.stream().map(SwStInputPassengerWorkOther::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            swStInputPassengerWorkOtherService.removeByIds(idList);
        }
        if(CollectionUtils.isNotEmpty(mergeList)){
            swStInputPassengerWorkOtherService.saveBatch(mergeList);
            if(isFlag){
                mergeList.forEach(x -> {
                    x.setLineCode(lineCode);
                    x.setStationCode(stationCode);
                    x.setSubmitStatus(CommonConstants.UN_SUBMIT);
                });
                swStInputPassengerWorkOtherService.updateBatchById(mergeList);
            }
        }
        return true;
    }

    /**
     * 乘客事务退换票合并
     * @param mergeData
     * @param unSubmit
     * @param isFlag
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean ticketPassagerWorkMergeData(SwStConductorSettle mergeData, List<String> unSubmit, Boolean isFlag) {
        // TODO 合并乘客事务退换票 根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次，日期
        LocalDate settleTime = mergeData.getSettleTime();//结算日期
        String conductorJobNo = mergeData.getConductorJobNo();//工号
        String conductorName = mergeData.getConductorName();//售票员名字
        String deviceOperateNum = mergeData.getDeviceOperateNum();//设备操作号
        String conductorShifts = mergeData.getConductorShifts();//班次
        String mergeConductorShifts = mergeData.getMergeConductorShifts();//合并班次
        String lineCode = mergeData.getLineCode();
        String stationCode = mergeData.getStationCode();
        List<SwStInputPassengerWorkTicket> mergeDatList = swStInputPassengerWorkTicketService.list(new QueryWrapper<SwStInputPassengerWorkTicket>()
                .eq("DATE_FORMAT(HANDLE_TIME, '%Y-%m-%d')",settleTime)
                .in("CONDUCTOR_CODE", conductorJobNo.split(","))
                .in("CLASS_NUMBER", mergeConductorShifts.split(","))
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("DEVICE_OPERATE_NUM", deviceOperateNum)
                .in("SUBMIT_STATUS", unSubmit)
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));

        if (CollectionUtils.isEmpty(mergeDatList)) {
            return false;
        }
        mergeDatList.forEach(x -> {
            x.setConductorName(conductorName);
            x.setConductorCode(conductorJobNo);
            x.setHandlePersonName(conductorName);
            x.setHandlePersonCode(conductorJobNo);
            x.setIsMerge("1");//是合并数据
            //x.setIsBeMergedId(passengerWorkMergeData.getId() + "," + swStInputPassengerWork.getId());//被合并的数据ID
            x.setMergeConductorShifts(mergeConductorShifts);//被合并的班次
            x.setClassNumber(conductorShifts);//班次为可选择的

        });
        //批量逻辑删除
        List<Integer> idList = mergeDatList.stream().map(SwStInputPassengerWorkTicket::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            swStInputPassengerWorkTicketService.removeByIds(idList);
        }
        if(CollectionUtils.isNotEmpty(mergeDatList)){
            swStInputPassengerWorkTicketService.saveBatch(mergeDatList);
            if(isFlag){
                mergeDatList.forEach(x -> {
                    x.setLineCode(lineCode);
                    x.setStationCode(stationCode);
                    x.setSubmitStatus(CommonConstants.UN_SUBMIT);
                });
                swStInputPassengerWorkTicketService.updateBatchById(mergeDatList);
            }
        }
        return true;
    }

    /**
     * 配票与配备用金合并
     * @param mergeData
     * @param unSubmit
     * @param isFlag
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean ticketPettyAddMergeData(SwStConductorSettle mergeData, List<String> unSubmit, Boolean isFlag) {
        // TODO 合并配票与配备用金 根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次，日期
        LocalDate settleTime = mergeData.getSettleTime();//结算日期
        String conductorJobNo = mergeData.getConductorJobNo();//工号
        String conductorName = mergeData.getConductorName();//售票员名字
        String deviceOperateNum = mergeData.getDeviceOperateNum();//设备操作号
        String conductorShifts = mergeData.getConductorShifts();//班次
        String mergeConductorShifts = mergeData.getMergeConductorShifts();//合并班次
        String lineCode = mergeData.getLineCode();
        String stationCode = mergeData.getStationCode();
        List<SwStTicketPettyAdd> mergeDatList = swStTicketPettyAddService.list(new QueryWrapper<SwStTicketPettyAdd>()
                .eq("DATE_FORMAT(WORKING_END_TIME, '%Y-%m-%d')",settleTime)
                .in("NS_JOB_NO", conductorJobNo.split(","))
                .in("NS_SHIFT", mergeConductorShifts.split(","))
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("DEVICE_OPERATE_NUM", deviceOperateNum)
                .eq("DEVICE_ATTRIBUTION", 1)//已归还
                .in("SUBMIT_STATUS", unSubmit)
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));
        if (CollectionUtils.isEmpty(mergeDatList)) {
            return false;
        }
        //配票与配备用金主表
        SwStTicketPettyAdd swStTicketPettyAddMerge = mergeDatList.get(0);
        //--------1.配备用金
        List<SwStTicketPettyAddCashDetails> firstCashDetailsList = swStTicketPettyAddCashDetailsService.getBaseMapper().selectList(
                Wrappers.<SwStTicketPettyAddCashDetails>lambdaQuery()
                        .eq(SwStTicketPettyAddCashDetails::getRelationId, swStTicketPettyAddMerge.getId())
                        .eq(SwStTicketPettyAddCashDetails::getDelFlag,"0")
        );
        List<SwStTicketPettyAddCashDetails> cashDetailsMergeList = new ArrayList<>();
        List<SwStTicketPettyAddCashDetails> cashDetailsRemoveList = new ArrayList<>();

        //--------2.配票
        List<SwStTicketPettyAddDetails> firstDetailsList = swStTicketPettyAddDetailsService.getBaseMapper().selectList(
                Wrappers.<SwStTicketPettyAddDetails>lambdaQuery()
                        .eq(SwStTicketPettyAddDetails::getRelationId, swStTicketPettyAddMerge.getId())
                        .eq(SwStTicketPettyAddDetails::getDelFlag,"0")
        );
        List<SwStTicketPettyAddDetails> detailsMergeList = new ArrayList<>();
        List<SwStTicketPettyAddDetails> detailsRemoveList = new ArrayList<>();

        if(mergeDatList.size() == 2){
            SwStTicketPettyAdd swStTicketPettyAdd = mergeDatList.get(1);
            swStTicketPettyAddMerge.setNsName(conductorName);
            swStTicketPettyAddMerge.setNsJobNo(conductorJobNo);
            swStTicketPettyAddMerge.setIsMerge("1");//是合并数据
            swStTicketPettyAddMerge.setIsBeMergedId(swStTicketPettyAddMerge.getId() + "," + swStTicketPettyAdd.getId());//被合并的数据ID
            swStTicketPettyAddMerge.setMergeConductorShifts(mergeConductorShifts);//被合并的班次
            swStTicketPettyAddMerge.setNsShift(conductorShifts);//班次为可选择的
            swStTicketPettyAddMerge.setTotalSpareAmount(swStTicketPettyAddMerge.getTotalSpareAmount().add(swStTicketPettyAdd.getTotalSpareAmount()));//合并配备用金金额
            swStTicketPettyAddMerge.setTotalHandSpareAmount(swStTicketPettyAddMerge.getTotalHandSpareAmount().add(swStTicketPettyAdd.getTotalHandSpareAmount()));//合并归还金额

            //----------1.合并配备用金
            List<SwStTicketPettyAddCashDetails> lastCashDetailsList = swStTicketPettyAddCashDetailsService.getBaseMapper().selectList(
                    Wrappers.<SwStTicketPettyAddCashDetails>lambdaQuery()
                            .eq(SwStTicketPettyAddCashDetails::getRelationId, swStTicketPettyAdd.getId())
                            .eq(SwStTicketPettyAddCashDetails::getDelFlag, "0")
            );
            if(CollectionUtils.isNotEmpty(lastCashDetailsList)){
                firstCashDetailsList.addAll(lastCashDetailsList);
            }
            // TODO 按配备用金类型：0表示首次配备用金 1表示新增配备金 2表示归还备用金保持一致合并
            // 分组统计配备用金
            Map<Integer,List<SwStTicketPettyAddCashDetails>> countMap = firstCashDetailsList.stream().collect(Collectors
                    .groupingBy(SwStTicketPettyAddCashDetails::getType, Collectors.toList()));

            if(countMap.isEmpty()){
                return false;
            }
            Set<Integer> keySet = countMap.keySet();
            for (Integer key : keySet) {
                List<SwStTicketPettyAddCashDetails> swStTicketPettyAddCashDetailsList = countMap.get(key);
                if(CollectionUtils.isNotEmpty(swStTicketPettyAddCashDetailsList)){
                    BigDecimal amount = swStTicketPettyAddCashDetailsList.stream()
                            // 将对象的mongey取出来map为Bigdecimal
                            .map(SwStTicketPettyAddCashDetails::getSpareAmount)
                            // 使用reduce聚合函数,实现累加器
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    SwStTicketPettyAddCashDetails cashDetailsMerge = swStTicketPettyAddCashDetailsList.get(0);
                    cashDetailsMerge.setSpareAmount(amount);
                    cashDetailsMergeList.add(cashDetailsMerge);
                    cashDetailsRemoveList.addAll(swStTicketPettyAddCashDetailsList);
                }
            }

            //---------2.合并配票
            List<SwStTicketPettyAddDetails> lastDetailsList = swStTicketPettyAddDetailsService.getBaseMapper().selectList(
                    Wrappers.<SwStTicketPettyAddDetails>lambdaQuery()
                            .eq(SwStTicketPettyAddDetails::getRelationId, swStTicketPettyAdd.getId())
                            .eq(SwStTicketPettyAddDetails::getDelFlag, "0")
            );
            if(CollectionUtils.isNotEmpty(lastDetailsList)){
                firstDetailsList.addAll(lastDetailsList);
            }
            // TODO 按配票类型：0 首次配票 1新增配票 2归还配票保持一致合并
            // 分组统计配票
            Map<String,List<SwStTicketPettyAddDetails>> countMap2 = firstDetailsList.stream().collect(Collectors
                    .groupingBy(o -> o.getType() + "_" + o.getTicketName() + "_" + o.getTicketType(), Collectors.toList()));

            if(countMap2.isEmpty()){
                return false;
            }
            Set<String> keySet2 = countMap2.keySet();
            for (String key : keySet2) {
                List<SwStTicketPettyAddDetails> swStTicketPettyAddDetailsList = countMap2.get(key);
                if(CollectionUtils.isNotEmpty(swStTicketPettyAddDetailsList)){
                    //开窗张数
                    int windowsNum = swStTicketPettyAddDetailsList.stream().mapToInt(SwStTicketPettyAddDetails::getWindowsNum).sum();
                    //关窗张数
                    int windowsCloseNum = swStTicketPettyAddDetailsList.stream().mapToInt(SwStTicketPettyAddDetails::getWindowsCloseNum).sum();
                    //废票张数
                    int invalidTicketNum = swStTicketPettyAddDetailsList.stream().mapToInt(SwStTicketPettyAddDetails::getInvalidTicketNum).sum();
                    //营销车票线下正常售卖张数
                    int cashSaleNum = swStTicketPettyAddDetailsList.stream().mapToInt(SwStTicketPettyAddDetails::getCashSaleNum).sum();
                    //营销车票线下正常售卖金额
                    BigDecimal cashSaleAmount = swStTicketPettyAddDetailsList.stream()
                            // 将对象的mongey取出来map为Bigdecimal
                            .map(SwStTicketPettyAddDetails::getCashSaleAmount)
                            // 使用reduce聚合函数,实现累加器
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    SwStTicketPettyAddDetails detailsMerge = swStTicketPettyAddDetailsList.get(0);
                    detailsMerge.setWindowsNum(windowsNum);
                    detailsMerge.setWindowsCloseNum(windowsCloseNum);
                    detailsMerge.setInvalidTicketNum(invalidTicketNum);
                    detailsMerge.setCashSaleNum(cashSaleNum);
                    detailsMerge.setCashSaleAmount(cashSaleAmount);
                    detailsMergeList.add(detailsMerge);
                    detailsRemoveList.addAll(swStTicketPettyAddDetailsList);
                }
            }

        }else {//you一条记录也算合并的
            swStTicketPettyAddMerge.setNsName(conductorName);
            swStTicketPettyAddMerge.setNsJobNo(conductorJobNo);
            swStTicketPettyAddMerge.setIsMerge("1");//是合并数据
            swStTicketPettyAddMerge.setIsBeMergedId(swStTicketPettyAddMerge.getId().toString());//被合并的数据ID
            swStTicketPettyAddMerge.setMergeConductorShifts(swStTicketPettyAddMerge.getNsShift());//被合并的班次
        }
        //配票与配备用金主表删除和合并
        List<Integer> idList = mergeDatList.stream().map(SwStTicketPettyAdd::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            swStTicketPettyAddService.removeByIds(idList);
        }

        swStTicketPettyAddService.save(swStTicketPettyAddMerge);
        if(isFlag){
            swStTicketPettyAddMerge.setLineCode(lineCode);
            swStTicketPettyAddMerge.setStationCode(stationCode);
            swStTicketPettyAddMerge.setSubmitStatus(CommonConstants.UN_SUBMIT);
            swStTicketPettyAddService.updateById(swStTicketPettyAddMerge);
        }

        int mainNewId = swStTicketPettyAddMerge.getId();//获取合并后主表的mainId

        //--------1.配备用金mainid和合并
        if(CollectionUtils.isNotEmpty(cashDetailsMergeList)){
            cashDetailsMergeList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
        }
        //逻辑删除配备用金
        //List<Integer> cashDetailsIdList = cashDetailsRemoveList.stream().map(SwStTicketPettyAddCashDetails::getId).collect(Collectors.toList());
//        if(CollectionUtils.isNotEmpty(cashDetailsRemoveList)){
//            cashDetailsRemoveList.forEach(x ->{
//                x.setDelFlag("1");
//            });
//            swStTicketPettyAddCashDetailsService.updateBatchById(cashDetailsRemoveList);
//        }
        //新增合并后的配备用金
        if(CollectionUtils.isNotEmpty(cashDetailsMergeList)){
            swStTicketPettyAddCashDetailsService.saveBatch(cashDetailsMergeList);
        }

        //--------2.配票mainid和合并
        if(CollectionUtils.isNotEmpty(detailsMergeList)){
            detailsMergeList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
        }
        //逻辑删除配票
        //List<Integer> detailsIdList = detailsRemoveList.stream().map(SwStTicketPettyAddDetails::getId).collect(Collectors.toList());
//        if(CollectionUtils.isNotEmpty(detailsRemoveList)){
//            detailsRemoveList.forEach(x ->{
//                x.setDelFlag("1");
//            });
//            swStTicketPettyAddDetailsService.updateBatchById(detailsRemoveList);
//        }
        //新增合并后的配票
        if(CollectionUtils.isNotEmpty(detailsMergeList)){
            swStTicketPettyAddDetailsService.saveBatch(detailsMergeList);
        }
        return true;
    }

    /**
     * 营销车票合并
     * @param mergeData
     * @param unSubmit
     * @param isFlag
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean marketingTicketMergeData(SwStConductorSettle mergeData, List<String> unSubmit, Boolean isFlag) {
        // TODO 合并营销车票 根据（日结账单取）记录被合并的售票员工号，设备操作号，记录被合并的班次，日期
        LocalDate settleTime = mergeData.getSettleTime();//结算日期
        String conductorJobNo = mergeData.getConductorJobNo();//工号
        String conductorName = mergeData.getConductorName();//售票员名字
        String deviceOperateNum = mergeData.getDeviceOperateNum();//设备操作号
        String conductorShifts = mergeData.getConductorShifts();//班次
        String mergeConductorShifts = mergeData.getMergeConductorShifts();//合并班次
        String lineCode = mergeData.getLineCode();
        String stationCode = mergeData.getStationCode();
        List<SwStMarketingTicket> mergeDatList = swStMarketingTicketService.list(Wrappers.<SwStMarketingTicket>lambdaQuery()
                .eq(SwStMarketingTicket::getLineCode, lineCode)
                .eq(SwStMarketingTicket::getStationCode, stationCode)
                .eq(SwStMarketingTicket::getDeviceOperateNum,deviceOperateNum)
                .in(SwStMarketingTicket::getConductorShifts, mergeConductorShifts.split(","))
                .in(SwStMarketingTicket::getConductorJobNo, conductorJobNo.split(","))
                .in(SwStMarketingTicket::getApprovalStatus, unSubmit)
                .eq(SwStMarketingTicket::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStMarketingTicket::getOpertorTime, settleTime)
                .eq(SwStMarketingTicket::getDelFlag, "0"));
        if (CollectionUtils.isEmpty(mergeDatList)) {
            return false;
        }
        //营销车票主表
        SwStMarketingTicket swStMarketingTicketMerge = mergeDatList.get(0);
        //取电子回执单
        List<SwStElectronicReceipt> mergeEleReceiptList = new ArrayList<>();
        if(swStMarketingTicketMerge.getRefElectronicPreviewId()!=null){
            SwStElectronicReceipt electronicReceipt = electronicReceiptService.getById(swStMarketingTicketMerge.getRefElectronicPreviewId());
            mergeEleReceiptList.add(electronicReceipt);
        }
        //--------1.线下取票
        List<SwStMarketingTicketOffineTakeTicket> firstOffineTakeList = takeTicketService.getBaseMapper().selectList(
                Wrappers.<SwStMarketingTicketOffineTakeTicket>lambdaQuery()
                        .eq(SwStMarketingTicketOffineTakeTicket::getRelationId, swStMarketingTicketMerge.getId())
                        .eq(SwStMarketingTicketOffineTakeTicket::getDelFlag,"0")
        );

        //--------2.团购售卖
        List<SwStMarketingTicketGroupSell> firstGroupSellList = ticketGroupSellService.getBaseMapper().selectList(
                Wrappers.<SwStMarketingTicketGroupSell>lambdaQuery()
                        .eq(SwStMarketingTicketGroupSell::getRelationId, swStMarketingTicketMerge.getId())
                        .eq(SwStMarketingTicketGroupSell::getDelFlag,"0")
        );

        //--------3.线下正常售卖
        List<SwStMarketingTicketOffineSell> firstOffineSellList = offineSellService.getBaseMapper().selectList(
                Wrappers.<SwStMarketingTicketOffineSell>lambdaQuery()
                        .eq(SwStMarketingTicketOffineSell::getRelationId, swStMarketingTicketMerge.getId())
                        .eq(SwStMarketingTicketOffineSell::getDelFlag,"0")
        );

        if(mergeDatList.size() == 2){
            SwStMarketingTicket swStMarketingTicket = mergeDatList.get(1);
            swStMarketingTicketMerge.setConductorName(conductorName);
            swStMarketingTicketMerge.setConductorJobNo(conductorJobNo);
            String bom = distinctBom(swStMarketingTicketMerge.getBomCode(),swStMarketingTicket.getBomCode());
            swStMarketingTicketMerge.setBomCode(BeanUtilsStm.bomOrJobNoSort(bom));// TODO bom公共方法去重排序
            swStMarketingTicketMerge.setIsMerge("1");//是合并数据
            swStMarketingTicketMerge.setIsBeMergedId(swStMarketingTicketMerge.getId() + "," + swStMarketingTicket.getId());//被合并的数据ID
            swStMarketingTicketMerge.setMergeConductorShifts(mergeConductorShifts);//被合并的班次
            swStMarketingTicketMerge.setConductorShifts(conductorShifts);//班次为可选择的
            swStMarketingTicketMerge.setTotalSellNum(swStMarketingTicketMerge.getTotalSellNum()+swStMarketingTicket.getTotalSellNum());
            swStMarketingTicketMerge.setTotalSellAmount(swStMarketingTicketMerge.getTotalSellAmount().add(swStMarketingTicket.getTotalSellAmount()));

            //取电子回执单
            if(swStMarketingTicket.getRefElectronicPreviewId()!=null){
                SwStElectronicReceipt electronicReceipt = electronicReceiptService.getById(swStMarketingTicket.getRefElectronicPreviewId());
                mergeEleReceiptList.add(electronicReceipt);
            }
            //----1.合并营收车票线下取票明细表
            List<SwStMarketingTicketOffineTakeTicket> lastOffineTakeList = takeTicketService.getBaseMapper().selectList(
                    Wrappers.<SwStMarketingTicketOffineTakeTicket>lambdaQuery()
                            .eq(SwStMarketingTicketOffineTakeTicket::getRelationId, swStMarketingTicket.getId())
            );
            if(CollectionUtils.isNotEmpty(lastOffineTakeList)){
                firstOffineTakeList.addAll(lastOffineTakeList);
            }

            //----2.合并营销车票团购售卖
            List<SwStMarketingTicketGroupSell> lastGroupSellList = ticketGroupSellService.getBaseMapper().selectList(
                    Wrappers.<SwStMarketingTicketGroupSell>lambdaQuery()
                            .eq(SwStMarketingTicketGroupSell::getRelationId, swStMarketingTicket.getId())
            );
            if(CollectionUtils.isNotEmpty(lastGroupSellList)){
                firstGroupSellList.addAll(lastGroupSellList);
            }

            //----3.合并线下正常售卖
            List<SwStMarketingTicketOffineSell> lastOffineSellList = offineSellService.getBaseMapper().selectList(
                    Wrappers.<SwStMarketingTicketOffineSell>lambdaQuery()
                            .eq(SwStMarketingTicketOffineSell::getRelationId, swStMarketingTicket.getId())
                            .eq(SwStMarketingTicketOffineSell::getDelFlag,"0")
            );
            if(CollectionUtils.isNotEmpty(lastOffineSellList)){
                firstOffineSellList.addAll(lastOffineSellList);
            }

        }else {//you一条记录也算合并的
            swStMarketingTicketMerge.setConductorName(conductorName);
            swStMarketingTicketMerge.setConductorJobNo(conductorJobNo);
            swStMarketingTicketMerge.setBomCode(BeanUtilsStm.bomOrJobNoSort(mergeData.getBomCode()));// TODO bom公共方法排序
            swStMarketingTicketMerge.setIsMerge("1");//是合并数据
            swStMarketingTicketMerge.setIsBeMergedId(swStMarketingTicketMerge.getId().toString());//被合并的数据ID
            swStMarketingTicketMerge.setMergeConductorShifts(swStMarketingTicketMerge.getConductorShifts());//被合并的班次
            swStMarketingTicketMerge.setConductorShifts(conductorShifts);//班次为可选择的
        }

        //营销车票逻辑删除和合并
        List<Integer> idList = mergeDatList.stream().map(SwStMarketingTicket::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            swStMarketingTicketService.removeByIds(idList);
        }

        swStMarketingTicketService.save(swStMarketingTicketMerge);
        if(isFlag){
            swStMarketingTicketMerge.setLineCode(lineCode);
            swStMarketingTicketMerge.setStationCode(stationCode);
            swStMarketingTicketMerge.setApprovalStatus(CommonConstants.UN_SUBMIT);
            swStMarketingTicketService.updateById(swStMarketingTicketMerge);
        }

        int mainNewId = swStMarketingTicketMerge.getId();//获取合并后的mainId

        //---处理合并电子回执单信息
        if(CollectionUtil.isNotEmpty(mergeEleReceiptList)){
            consolidateElectronicReceipt(mergeEleReceiptList,swStMarketingTicketMerge,isFlag);
        }


        //---1.营收车票线下取票明细表新增合并后数据
        if(CollectionUtils.isNotEmpty(firstOffineTakeList)){
            firstOffineTakeList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            takeTicketService.saveBatch(firstOffineTakeList);
        }

        //---2.营销车票团购售卖新增合并后数据
        if(CollectionUtils.isNotEmpty(firstGroupSellList)){
            firstGroupSellList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            ticketGroupSellService.saveBatch(firstGroupSellList);
        }

        //---3.线下正常售卖新增合并后数据
        if(CollectionUtils.isNotEmpty(firstOffineSellList)){
            firstOffineSellList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            offineSellService.saveBatch(firstOffineSellList);
        }
        return true;
    }

    /**
     * 处理合并电子回执单
     * @param mergeEleReceiptList
     * @param swStMarketingTicketMerge
     * @param isFlag
     */
    private void consolidateElectronicReceipt(List<SwStElectronicReceipt> mergeEleReceiptList, SwStMarketingTicket swStMarketingTicketMerge, Boolean isFlag) {
        SwStElectronicReceipt electronicReceiptMerge = mergeEleReceiptList.get(0);
        //----合并电子回执单子表
        List<SwStElectronicReceiptDetails> firstElecReceiptDetailsList = detailsService.getBaseMapper().selectList(
                Wrappers.<SwStElectronicReceiptDetails>lambdaQuery()
                        .eq(SwStElectronicReceiptDetails::getRelationId, electronicReceiptMerge.getId())
        );
        if(mergeEleReceiptList.size() == 2){
            SwStElectronicReceipt electronicReceiptMergeTwo = mergeEleReceiptList.get(1);
            electronicReceiptMerge.setConductorName(swStMarketingTicketMerge.getConductorName());
            electronicReceiptMerge.setConductorJobNo(swStMarketingTicketMerge.getConductorJobNo());
            electronicReceiptMerge.setIsMerge("1");//是合并数据
            electronicReceiptMerge.setIsBeMergedId(swStMarketingTicketMerge.getId().toString());//被合并的数据ID
            electronicReceiptMerge.setMergeConductorShifts(swStMarketingTicketMerge.getConductorShifts());//被合并的班次
            electronicReceiptMerge.setConductorShifts(swStMarketingTicketMerge.getConductorShifts());//班次为可选择的
            electronicReceiptMerge.setTotalSellNum(electronicReceiptMerge.getTotalSellNum()+electronicReceiptMergeTwo.getTotalSellNum());
            electronicReceiptMerge.setTotalSellAmount(electronicReceiptMerge.getTotalSellAmount().add(electronicReceiptMergeTwo.getTotalSellAmount()));
            electronicReceiptMerge.setTotalTransferAmount(electronicReceiptMerge.getTotalTransferAmount().add(electronicReceiptMergeTwo.getTotalTransferAmount()));

            List<SwStElectronicReceiptDetails> lastElecReceiptDetailsList = detailsService.getBaseMapper().selectList(
                    Wrappers.<SwStElectronicReceiptDetails>lambdaQuery()
                            .eq(SwStElectronicReceiptDetails::getRelationId, electronicReceiptMergeTwo.getId())
            );
            if(CollectionUtils.isNotEmpty(lastElecReceiptDetailsList)){
                firstElecReceiptDetailsList.addAll(lastElecReceiptDetailsList);
            }
        }else {//you一条记录也算合并的
            electronicReceiptMerge.setConductorName(swStMarketingTicketMerge.getConductorName());
            electronicReceiptMerge.setConductorJobNo(swStMarketingTicketMerge.getConductorJobNo());
            electronicReceiptMerge.setIsMerge("1");//是合并数据
            electronicReceiptMerge.setIsBeMergedId(swStMarketingTicketMerge.getId().toString());//被合并的数据ID
            electronicReceiptMerge.setMergeConductorShifts(swStMarketingTicketMerge.getMergeConductorShifts());//被合并的班次
            electronicReceiptMerge.setConductorShifts(swStMarketingTicketMerge.getConductorShifts());//班次为可选择的

        }

        //电子回执单逻辑删除和合并
        List<Integer> idList = mergeEleReceiptList.stream().map(SwStElectronicReceipt::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(idList)){
            electronicReceiptService.removeByIds(idList);
        }

        electronicReceiptService.save(electronicReceiptMerge);
        if(isFlag){
            electronicReceiptMerge.setLineCode(swStMarketingTicketMerge.getLineCode());
            electronicReceiptMerge.setStationCode(swStMarketingTicketMerge.getStationCode());
            electronicReceiptMerge.setApprovalStatus(CommonConstants.UN_SUBMIT);
            electronicReceiptService.updateById(electronicReceiptMerge);
        }

        int mainNewId = electronicReceiptMerge.getId();//获取合并后的mainId

        //同步营销车票主表关联id
        swStMarketingTicketMerge.setRefElectronicPreviewId(mainNewId);
        swStMarketingTicketService.updateById(swStMarketingTicketMerge);

        //---电子回执单明细表新增合并后数据
        if(CollectionUtils.isNotEmpty(firstElecReceiptDetailsList)){
            firstElecReceiptDetailsList.forEach(x ->{
                x.setId(null);
                x.setRelationId(mainNewId);
            });
            detailsService.saveBatch(firstElecReceiptDetailsList);
        }
    }

    /**
     * bom合并
     * @param bomCode
     * @param bomCode1
     * @return
     */
    private String distinctBom(String bomCode, String bomCode1) {
        String[] split = bomCode.split(",");
        String[] split1 = bomCode1.split(",");
        List<String> list = Arrays.asList(split);
        List<String> list1 = Arrays.asList(split1);
        List<String> arrList = new ArrayList(list);
        arrList.addAll(list1);
        String result = arrList.stream().distinct().map(String::valueOf).collect(Collectors.joining(","));
        return result;
    }

    /**
     * 字符串比较大小并替换
     * @param mergeData
     * @param settleData
     * @return
     */
    public void compareJobNoTrunReplace(SwStConductorSettle mergeData, SwStConductorSettle settleData){
        String conductorJobNo1 = mergeData.getConductorJobNo();
        String conductorName1 = mergeData.getConductorName();
        String conductorJobNo2 = settleData.getConductorJobNo();
        String conductorName2 = settleData.getConductorName();
        int c = mergeData.getConductorJobNo().compareTo(settleData.getConductorJobNo());
        //大于0交换
        if(c > 0){
            String jobNo = conductorJobNo2 +","+ conductorJobNo1;
            String jobName = conductorName2 +","+ conductorName1;
            mergeData.setConductorJobNo(jobNo);
            mergeData.setConductorName(jobName);
        }
        if(c == 0){
            mergeData.setConductorJobNo(conductorJobNo1);
            mergeData.setConductorName(conductorName1);
        }
        if(c < 0){
            String jobNo = conductorJobNo1 +","+ conductorJobNo2;
            String jobName = conductorName1 +","+ conductorName2;
            mergeData.setConductorJobNo(jobNo);
            mergeData.setConductorName(jobName);
        }

    }
    @Override
    public SwStConductorSettleDto queryNeedToConfirmData(CommomConfirmInfoDTO confirmInfoDTO) {
        LocalDate date = confirmInfoDTO.getDate();
        String lineCode = SecurityUtils.getUser().getLineCode();
        String stationCode = SecurityUtils.getUser().getStationCode();
        confirmInfoDTO.setNsJobNo(BeanUtilsStm.bomOrJobNoSort(confirmInfoDTO.getNsJobNo()));//售票员工号排序
        List<SwStConductorSettle> data = swStConductorSettleMapper.selectList(new QueryWrapper<SwStConductorSettle>().lambda().eq(SwStConductorSettle::getSettleTime, date).eq(SwStConductorSettle::getDelFlag,0)
                .eq(SwStConductorSettle::getConductorShifts, confirmInfoDTO.getNsShift()).in(SwStConductorSettle::getConductorJobNo, confirmInfoDTO.getNsJobNo())
                .eq(SwStConductorSettle::getLineCode,lineCode).eq(SwStConductorSettle::getStationCode,stationCode));
        if (null == data) {
            return null;
        }
        if(data.size()>1){
            throw new RuntimeException("请检查售票员“" + data.get(0).getConductorName() + "”在该班次存在" + data.size() + "条售票员日结算数据！");
        }
        SwStConductorSettleDto swStConductorSettleDto = new SwStConductorSettleDto();
        if(data.size()>0){
            swStConductorSettleDto.setSwStConductorSettle(data.get(0));
        }
        return swStConductorSettleDto;
        //return getCascadeById(data.getId());
    }

    @Override
    public boolean confirmData(Integer id) {
        SwStConductorSettle settle = new SwStConductorSettle();
        settle.setId(id);
        //状态确认
        settle.setConfirmStatus("1");
        updateById(settle);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean confirmAllData(CommomConfirmInfoDTO confirmInfoDTO) {

        String  line_code= SecurityUtils.getUser().getLineCode();
        String sation_code=SecurityUtils.getUser().getStationCode();
        try {
            String nsJobNo= confirmInfoDTO.getNsJobNo();
            //售票员工号比较排序
            nsJobNo = BeanUtilsStm.bomOrJobNoSort(nsJobNo);
            //配备用金确认SQL
            String startTime = DateFormat.LocalDateTurnString(confirmInfoDTO.getDate())+" 02:00:00";
            String endTime = DateFormat.LocalDateTurnString(confirmInfoDTO.getDate().plusDays(1))+" 01:59:59";//加一天
            JdbcUtil.exeSqlCrud("update sw_st_ticket_petty_add set CONFIRM_STATUS='1' " +
                    " where line_code= '"+line_code+"'" +
                    " and station_code= '"+sation_code+"'" +
                    " and NS_JOB_NO= '"+nsJobNo+"'" +
                    " and NS_SHIFT='"+confirmInfoDTO.getNsShift()+"'" +
                    " and DEL_FLAG='0' " +
                    " and CONFIRM_STATUS='0' " +
                    " and WORKING_END_TIME is not null " +
                    " and WORKING_END_TIME between '"+startTime+"' and '"+endTime+"' ");
            //售票员日结算单确认SQL
            JdbcUtil.exeSqlCrud("update sw_st_conductor_settle  set CONFIRM_STATUS='1',PASSENGER_ATTENDANT_JOB_NO= '"+
                    SecurityUtils.getUser().getUserCode()+"',"+
                    " PASSENGER_ATTENDANT_NAME = '"+SecurityUtils.getUser().getNikeName()+"'"+
                    " where line_code= '"+line_code+"'" +
                    " and station_code= '"+sation_code+"'" +
				    " and CONDUCTOR_JOB_NO= '"+nsJobNo+"'" +
                    " and CONDUCTOR_SHIFTS='"+confirmInfoDTO.getNsShift()+"'" +
                    //"or (find_in_set('"+confirmInfoDTO.getNsJobNo()+"',CONDUCTOR_JOB_NO) and LOCATE(',',REALTION_MARKETING_ID)>0)  )"+
                    //" and CONDUCTOR_JOB_NO= '"+confirmInfoDTO.getNsJobNo()+"'" +
                    //" and CONDUCTOR_SHIFTS='"+confirmInfoDTO.getNsShift()+"'" +
                    " and DEL_FLAG='0' " +
                    " and SETTLE_TIME= '" + confirmInfoDTO.getDate()+"'");
            //乘客事务确认SQL
            JdbcUtil.exeSqlCrud("update sw_st_input_passenger_work   set CONFIRM_STATUS='1' " +
                    " where line_code= '"+line_code+"'" +
                    " and station_code= '"+sation_code+"'" +
                    " and CONDUCTOR_CODE= '"+nsJobNo+"'" +
                    " and CLASS_NUMBER='"+confirmInfoDTO.getNsShift()+"'" +
                    " and DEL_FLAG='0' " +
                    " and WORK_DATE= '" + confirmInfoDTO.getDate()+"'");

            //乘客事务--其他相关数据录入原来子页面里的确认SQL
            JdbcUtil.exeSqlCrud("update sw_st_input_passenger_work_other   set CONFIRM_STATUS='1' " +
                    " where line_code= '"+line_code+"'" +
                    " and station_code= '"+sation_code+"'" +
                    " and CONDUCTOR_CODE= '"+nsJobNo+"'" +
                    " and CLASS_NUMBER='"+confirmInfoDTO.getNsShift()+"'" +
                    " and DEL_FLAG='0' " +
                    " and DATE_FORMAT(INPUT_TIME, '%Y-%m-%d')= '" + confirmInfoDTO.getDate()+"'");
            //乘客事务--即时非即时，原来子页面里的确认SQL
            JdbcUtil.exeSqlCrud("update sw_st_input_passenger_work_ticket   set CONFIRM_STATUS='1' " +
                    " where line_code= '"+line_code+"'" +
                    " and station_code= '"+sation_code+"'" +
                    " and HANDLE_PERSON_CODE= '"+nsJobNo+"'" +
                    " and CLASS_NUMBER='"+confirmInfoDTO.getNsShift()+"'" +
                    " and DEL_FLAG='0' " +
                    " and DATE_FORMAT(HANDLE_TIME, '%Y-%m-%d')= '" + confirmInfoDTO.getDate()+"'");
            //乘客事务--即时退换票
			/*  票卡信息功能已经不用，去掉相关业务逻辑处理 20231221
            //即时退换票客值确认成功之后存入收入审核票卡信息查询
            List<Map<String, Object>> maps = JdbcUtil.exeSqlQuery("select * from sw_st_input_passenger_work_ticket " +
                    " where CONFIRM_STATUS='1' " +
                    " and SUBMIT_STATUS= '0'" +
                    " and operation_type= '0'" +
                    " and LENGTH(card_order)!= 0 " +
                    " and line_code= '" + line_code + "'" +
                    " and station_code= '" + sation_code + "'" +
                    " and HANDLE_PERSON_CODE= '" + nsJobNo + "'" +
                    " and CLASS_NUMBER='" + confirmInfoDTO.getNsShift() + "'" +
                    " and DEL_FLAG='0' " +
                    " and DATE_FORMAT(HANDLE_TIME, '%Y-%m-%d')= '" + confirmInfoDTO.getDate() + "'");
            if(maps!=null){
                List<SwStTicketInformationCheck> saveList = new ArrayList<>();
                List<SwStTicketInformationCheck> updateList = new ArrayList<>();
                maps.forEach(item ->{
                    QueryWrapper<SwStTicketInformationCheck> queryWrapper = new QueryWrapper<>();
                    //根据原卡号查询判断
                    queryWrapper.lambda().eq(SwStTicketInformationCheck::getCardOrder, item.get("CARD_ORDER"));
                    SwStTicketInformationCheck swStTicketInformationCheckServiceOne = swStTicketInformationCheckService
                            .getOne(queryWrapper);
                    if(swStTicketInformationCheckServiceOne == null){
                            SwStTicketInformationCheck swStTicketInformationCheck = new SwStTicketInformationCheck();
                            swStTicketInformationCheck.setSubmitLineCode(line_code);
                            swStTicketInformationCheck.setSubmitStationCode(sation_code);
                            swStTicketInformationCheck.setCardOrder((String) item.get("CARD_ORDER"));
                            if(item.get("AMOUNT") != null){
                                swStTicketInformationCheck.setAmount((BigDecimal) item.get("AMOUNT"));
                            }else {
                                swStTicketInformationCheck.setAmount((BigDecimal) item.get("ESTIMATED_NUMBER"));
                            }
                            swStTicketInformationCheck.setInputPersonCode((String) item.get("HANDLE_PERSON_CODE"));
                            swStTicketInformationCheck.setInputPerson((String) item.get("HANDLE_PERSON_NAME"));
                            Timestamp handle_time = (Timestamp)item.get("HANDLE_TIME");
                            LocalDateTime localDateTime = handle_time.toLocalDateTime();
                            swStTicketInformationCheck.setInputTime(localDateTime);
                            swStTicketInformationCheck.setDelFlag("0");
                            swStTicketInformationCheck.setRelationId((Integer) item.get("ID"));
                            PigxUser user = SecurityUtils.getUser();
                            swStTicketInformationCheck.setDeptId(user.getDeptId());
                            swStTicketInformationCheck.setCreatorId(user.getId());
                            swStTicketInformationCheck.setCreatorName(user.getNikeName());
                            saveList.add(swStTicketInformationCheck);
                        }
                    else {
                        if(item.get("AMOUNT") != null){
                            swStTicketInformationCheckServiceOne.setAmount((BigDecimal) item.get("AMOUNT"));
                        }else {
                            swStTicketInformationCheckServiceOne.setAmount((BigDecimal) item.get("ESTIMATED_NUMBER"));
                        }
                        swStTicketInformationCheckServiceOne.setInputPersonCode((String) item.get("HANDLE_PERSON_CODE"));
                        swStTicketInformationCheckServiceOne.setInputPerson((String) item.get("HANDLE_PERSON_NAME"));
                        Timestamp handle_time = (Timestamp)item.get("HANDLE_TIME");
                        LocalDateTime localDateTime = handle_time.toLocalDateTime();
                        swStTicketInformationCheckServiceOne.setInputTime(localDateTime);
                        swStTicketInformationCheckServiceOne.setDelFlag("0");
                        swStTicketInformationCheckServiceOne.setRelationId((Integer) item.get("ID"));
                        updateList.add(swStTicketInformationCheckServiceOne);
                    }
                });
                if (saveList.size()>0) {
                    swStTicketInformationCheckService.saveBatch(saveList);
                }
                if (updateList.size()>0){
                    swStTicketInformationCheckService.updateBatchById(updateList);
                }
            }*/
            //客值确认时，调动此方法的逻辑
			saveMarketingTicket(confirmInfoDTO);


        }catch (Exception e){
            System.out.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return true;
    }
    public boolean saveMarketingTicket(CommomConfirmInfoDTO confirmInfoDTO){
		/*客值确认时，调动此方法的逻辑
		配票归还数据获取内容：票种，车票名称  金额/次数（单价） 现金售卖张数  现金售卖金额   合计售卖张数、合计售卖金额（两个合计值实际就是现金售卖张数  现金售卖金额）插入到线下正常售卖中
		（只取ticket_name='YXCP'，type='2'  del_flag=0 cash_sale_num>0 and cash_sale_amount>0） ==ticketPrePay

		    2.根据客值确认界面带过来的     线路、站点、售票员操作号、班次、收益日期、售票员工号、删除标识查找营销车票主表数据
		     2.1 主表不存在数据，从配票归还子表内查找ticket_name='YXCP'，type='2'  del_flag=0 标识  cash_sale_num>0,cash_sale_amount>0的记录的数据，直接插入主表和子表，主表的del_flag等默认值要设置上
			 2.2 主表存在，先全部删除线下正常售卖子表（保障之前有删归还等未同步的数据），再从配票归还子表内查找ticket_name='YXCP'，type='2'  del_flag=0 标识 cash_sale_num>0,cash_sale_amount>0的记录的数据 直接插入子表，并重新计算更新主表的总售卖张数和金额，原来的总张数和总金额累加
		    var  ticketPrepay = a ;  //先查询出来归还明细中存在的该售票员售卖的的营销车票
			if(营销车票主表存在){
			      int mainId = 1111;//营销车票主表ID
				  int amount = 0; //营销车票合计数量
				  BigDecimal mooney = new BigDecimal(0.00);  //营销车票合计金额
				  delete 真删，营销车票正常售卖子表数据 保证清除垃圾数据（根据主表ID，查找子表的relation_id 关联删除）

				  if(ticketPrepay.size()>0){  //第一步查询出来的配票明细营销车票对象列表
				    //1. 循环或者执行批量插入营销车票子表（包括营销车票类型、营销现金售卖数量、现金售卖金额以及合计数量和合计金额），//并重新计算主表的总张数和总金额数据（线下取票和团购折扣后的金额+配票金额和数量），
				       for(int ticketPrepay){
					     amout++;
                         money++   //2.  将配票中的营销车票总数和金额  赋值到 amout 和money变量
					   }

					//3. 获取团购和线下取票金额SQL
					 select ifnull(sum(sell_num),0) as amount,ifnull(sum(discount_amount),0) as money  from sw_st_marketing_ticket_group_sell where  relation_id= 1051(mainId) and del_flag='0'

                     select ifnull(sum(ticket_num),0) as amount,ifnull(sum(sell_amount),0) as money  from sw_st_marketing_ticket_offine_take_ticket where relation_id=1051(mainId) and del_flag='0'
                     根据获得的两个表的数量和金额累加再累加到amout 和money中
				  }
				  update 将营销车票主表的确认状态置为1（//实际完成上面那行营销车票确认SQL），主表的总张数和总金额数据（amout,money值）


			}else{//主表不存在  sw_st_marketing_ticket  营销车票主表   sw_st_marketing_ticket_offine_sell 线下正常售卖
			   if(ticketPrepay>0){
			      //插入营销车票主、子表，并更新总张数和总金额数据（总张数和总金额就只算配票中的金额和数量即可）
				   update 将主表的确认状态置为1（//实际完成上面那行营销车票确认SQL），主表的总张数和总金额数据
			   }
			}
		*/
        /*
        		配票归还数据获取内容：票种，车票名称  金额/次数（单价） 现金售卖张数  现金售卖金额   合计售卖张数、合计售卖金额（两个合计值实际就是现金售卖张数  现金售卖金额）插入到线下正常售卖中
		（只取ticket_name='YXCP'，type='2'  del_flag=0 cash_sale_num>0 and cash_sale_amount>0） ==ticketPrePay

		    2.根据客值确认界面带过来的     线路、站点、售票员操作号、班次、收益日期、售票员工号、删除标识查找营销车票主表数据
         */

//////////////////////////////////////////同时调整SwStTicketPettyAddServiceImpl////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////同时调整SwStTicketPettyAddServiceImpl////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////同时调整SwStTicketPettyAddServiceImpl////////////////////////////////////////////////////////////////////////////////////////
        String lineCode = SecurityUtils.getUser().getLineCode();
        String stationCode = SecurityUtils.getUser().getStationCode();
        //1.查询配票表的主表
        LocalDate date = confirmInfoDTO.getDate();
        String nsJobNo= confirmInfoDTO.getNsJobNo();
        String nsShift = confirmInfoDTO.getNsShift();
        //售票员工号比较排序
        nsJobNo = BeanUtilsStm.bomOrJobNoSort(nsJobNo);
        SwStTicketPettyAdd pettyAdd = stTicketPettyAddMapper.selectOne(new QueryWrapper<SwStTicketPettyAdd>().lambda()
                .ge(SwStTicketPettyAdd::getWorkingStartTime, date)
                .le(SwStTicketPettyAdd::getWorkingStartTime, date.plusDays(1))
                .eq(SwStTicketPettyAdd::getNsShift, confirmInfoDTO.getNsShift())
                .eq(SwStTicketPettyAdd::getNsJobNo, nsJobNo)//售票员工号排序
                .eq(SwStTicketPettyAdd::getLineCode, lineCode)
                .eq(SwStTicketPettyAdd::getStationCode, stationCode)
                .eq(SwStTicketPettyAdd::getDelFlag, "0"));

        //2.查询出归还明细中存在的该售票员售卖的的营销车票
        //配票归还数据获取内容：票种，车票名称  金额/次数（单价） 现金售卖张数  现金售卖金额   合计售卖张数、合计售卖金额（两个合计值实际就是现金售卖张数  现金售卖金额）插入到线下正常售卖中
        if(pettyAdd != null) {

            SwStMarketingTicket marketingTicket = new SwStMarketingTicket();
            marketingTicket.setLineCode(pettyAdd.getLineCode());
            marketingTicket.setStationCode(pettyAdd.getStationCode());
            marketingTicket.setOpertorTime(DateUtilStm.stringTolocalDate(pettyAdd.getWorkingStartTime()));
            marketingTicket.setConductorName(pettyAdd.getNsName());
            marketingTicket.setConductorId(pettyAdd.getNsId());
            marketingTicket.setConductorJobNo(pettyAdd.getNsJobNo());
            marketingTicket.setConductorShifts(pettyAdd.getNsShift());
            marketingTicket.setDeviceOperateNum(pettyAdd.getDeviceOperateNum());
            marketingTicket.setEntryUpdateJobName(pettyAdd.getEntryUpdateJobName());
            marketingTicket.setEntryUpdateJobNo(pettyAdd.getEntryUpdateJobNo());
            marketingTicket.setEntryUpdateTime(pettyAdd.getEntryUpdateTime());
            //将营销车票主表的确认状态置为1
            marketingTicket.setConfirmStatus("1");
            marketingTicket.setDelFlag("0");

            //营销车票主表 2.根据客值确认界面带过来的     线路、站点、售票员操作号、班次、收益日期、售票员工号、删除标识查找 营销车票主表数据
            SwStMarketingTicket swStMarketingTicket = swStMarketingTicketService.getBaseMapper().selectOne(Wrappers.<SwStMarketingTicket>lambdaQuery()
                    .eq(SwStMarketingTicket::getLineCode, marketingTicket.getLineCode())
                    .eq(SwStMarketingTicket::getStationCode, marketingTicket.getStationCode())
                    .eq(SwStMarketingTicket::getDeviceOperateNum,marketingTicket.getDeviceOperateNum())
                    .eq(SwStMarketingTicket::getConductorShifts, marketingTicket.getConductorShifts())
                    .eq(SwStMarketingTicket::getConductorJobNo, marketingTicket.getConductorJobNo())
                    .eq(SwStMarketingTicket::getOpertorTime, marketingTicket.getOpertorTime())
                    .eq(SwStMarketingTicket::getDelFlag, "0"));

            //根据配票主表ID，查询配票明细表时，只查ticket_name='YXCP'，type='2'  del_flag=0 cash_sale_num>0 and cash_sale_amount>0的数据（过滤掉非营销车票数据）
            List<SwStTicketPettyAddDetails> pettyAddDetails = swStTicketPettyAddDetailsMapper.getTicketPettyAddDetails(pettyAdd.getId());

            ////如果营销车票主表不存在，并且配票明细表不为空    插入主表和子表 并更新总张数和总金额数据（总张数和总金额就只算配票中的金额和数量即可）
            if (swStMarketingTicket == null && CollectionUtils.isNotEmpty(pettyAddDetails)) {
                //线下售卖营销车票总张数
                int cashSaleNumTotal = pettyAddDetails.stream().mapToInt(SwStTicketPettyAddDetails::getCashSaleNum).sum();
                //线下售卖营销车票总金额
                BigDecimal cashSaleAmountSum = pettyAddDetails.stream().map(SwStTicketPettyAddDetails::getCashSaleAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
                //营销车票主表不存在查bom编号
                SwStConductorSettle conductorSettle = swStConductorSettleMapper.selectOne(Wrappers.<SwStConductorSettle>lambdaQuery()
                        .eq(SwStConductorSettle::getLineCode, SecurityUtils.getUser().getLineCode())
                        .eq(SwStConductorSettle::getStationCode, SecurityUtils.getUser().getStationCode())
                        .eq(SwStConductorSettle::getConductorShifts, confirmInfoDTO.getNsShift())
                        .eq(SwStConductorSettle::getConductorJobNo, confirmInfoDTO.getNsJobNo())
                        .eq(SwStConductorSettle::getSettleTime, confirmInfoDTO.getDate())
                        .eq(SwStConductorSettle::getDelFlag, "0"));

                if(conductorSettle!=null){
                    marketingTicket.setBomCode(conductorSettle.getBomCode());
                }
                marketingTicket.setTotalSellNum(cashSaleNumTotal);
                marketingTicket.setTotalSellAmount(cashSaleAmountSum);
                //插入营销车票主表
                swStMarketingTicketService.save(marketingTicket);
                //获取营销车票主表id
                Integer rid = marketingTicket.getId();

                //处理营销车票从表添加逻辑
                List<SwStMarketingTicketOffineSell> ticketOffineSells = addTicketOffineSells(pettyAddDetails);
                //保存营销车票从表
                if (CollectionUtils.isNotEmpty(ticketOffineSells)) {
                    ticketOffineSells.forEach(x -> x.setRelationId(rid));//营销车票主表id
                    offineSellService.saveBatch(ticketOffineSells);
                }

            }else if(swStMarketingTicket != null) {//营销车票主表存在
                //营销车票存在，配票存在处理
                marketingTicketExistenceProcessing(swStMarketingTicket,pettyAddDetails);
            }


        }else {
            //营销车票sql
            SwStMarketingTicket swStMarketingTicket = swStMarketingTicketService.getBaseMapper().selectOne(Wrappers.<SwStMarketingTicket>lambdaQuery()
                    .eq(SwStMarketingTicket::getLineCode, lineCode)
                    .eq(SwStMarketingTicket::getStationCode, stationCode)
                    .eq(SwStMarketingTicket::getConductorShifts, nsShift)
                    .eq(SwStMarketingTicket::getConductorJobNo, nsJobNo)
                    .eq(SwStMarketingTicket::getOpertorTime, date)
                    .eq(SwStMarketingTicket::getDelFlag, "0"));
            //营销车票存在，配票不存在处理
            if(ObjectUtil.isNotEmpty(swStMarketingTicket)){
                marketingTicketExistenceProcessing(swStMarketingTicket,null);
            }
        }

        return true;
    }

    /**
     * 导出
     * @param dto
     * @param response
     */
    @Override
    public void export(SwStConductorSettle dto, HttpServletResponse response) {
        PigxUser user = SecurityUtils.getUser();
        String lineCode = user.getLineCode();
        String stationCode = user.getStationCode();

        AtomicInteger i1 = new AtomicInteger(0);
        AtomicInteger i2 = new AtomicInteger(0);
        AtomicInteger i3 = new AtomicInteger(0);
        AtomicInteger i4 = new AtomicInteger(0);
        AtomicInteger i5 = new AtomicInteger(0);
        AtomicInteger i6 = new AtomicInteger(0);
        AtomicInteger i7 = new AtomicInteger(0);
        AtomicInteger i8 = new AtomicInteger(0);
        AtomicInteger i9 = new AtomicInteger(0);
        AtomicInteger i10 = new AtomicInteger(0);
        AtomicInteger i11 = new AtomicInteger(0);
        AtomicInteger i12 = new AtomicInteger(0);
        //获取班次名称
        Map<String, String> mapShifts = new HashMap<>();
        List<Map<String,String>> conductorShiftsMap = swStConductorSettleMapper.selectConductorShiftsMap();
        conductorShiftsMap.forEach(x -> {
            mapShifts.put(x.get("conductorShiftsFlag"),x.get("conductorShiftsName"));
        });
        //获取车票名称
        Map<String, String> ticketMap = new HashMap<>();
        List<Map<String,String>> ticketMapList = swStConductorSettleMapper.selectTicketMap();
        ticketMapList.forEach(map -> {
            ticketMap.put(map.get("SUB_EN_NAME"),map.get("SUB_NAME"));
        });

        //第一部分 查线路、站点、日期
        List<Map<String,String>> stationMap = swStConductorSettleMapper.selectStationMap();
        String lineName = getExportLineName(stationMap, lineCode);
        String stationName = getExportStationName(stationMap, stationCode, lineCode);
        LocalDate settleTime = dto.getSettleTime();
        //第二部分 查售票员结算单
        List<SwStConductorSettle> settleList = swStConductorSettleMapper.selectList(Wrappers.<SwStConductorSettle>lambdaQuery()
                .eq(SwStConductorSettle::getLineCode, lineCode)
                .eq(SwStConductorSettle::getStationCode, stationCode)
                .eq(SwStConductorSettle::getSettleTime, dto.getSettleTime())
                .eq(SwStConductorSettle::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStConductorSettle::getDelFlag, "0"));
        if(CollectionUtil.isNotEmpty(settleList)){
            settleList.forEach(x -> {
                x.setId(i1.incrementAndGet());
                x.setConductorShifts(mapShifts.get(x.getConductorShifts()));
            });
        }else {
            return ;
        }

        //第三部分 查配票归还信息
        List<SwStTicketPettyAddDetailsDto> pettyAddList = new ArrayList<>();
        List<SwStTicketPettyAdd> pettyAdds = swStTicketPettyAddService.list(new QueryWrapper<SwStTicketPettyAdd>()
                .eq("DATE_FORMAT(WORKING_END_TIME, '%Y-%m-%d')",settleTime)
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("DEVICE_ATTRIBUTION", 1)//已归还
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));


        if(CollectionUtil.isNotEmpty(pettyAdds)){
            //根据主表id关联查出子表归还信息
            pettyAdds.forEach(x -> {
                List<SwStTicketPettyAddDetails> detailsList = swStTicketPettyAddDetailsService.getBaseMapper().selectList(
                        Wrappers.<SwStTicketPettyAddDetails>lambdaQuery()
                                .eq(SwStTicketPettyAddDetails::getRelationId, x.getId())
                                .eq(SwStTicketPettyAddDetails::getType, "2")//归还
                                .eq(SwStTicketPettyAddDetails::getDelFlag,"0")
                );
                if(CollectionUtil.isNotEmpty(detailsList)){
                    detailsList.forEach(details -> {
                        SwStTicketPettyAddDetailsDto swStTicketPettyAddDetailsDto = new SwStTicketPettyAddDetailsDto();
                        BeanUtils.copyProperties(details,swStTicketPettyAddDetailsDto);
                        swStTicketPettyAddDetailsDto.setId(i2.incrementAndGet());
                        swStTicketPettyAddDetailsDto.setConductorName(x.getNsName());
                        ticketMapList.forEach(map -> {
                            if(map.get("SUB_EN_NAME").equals(swStTicketPettyAddDetailsDto.getTicketType()) && map.get("MAIN_EN_NAME").equals(swStTicketPettyAddDetailsDto.getTicketName())){
                                swStTicketPettyAddDetailsDto.setTicketName(map.get("MAIN_NAME"));
                                swStTicketPettyAddDetailsDto.setTicketType(map.get("SUB_NAME"));
                            }
                        });
                        pettyAddList.add(swStTicketPettyAddDetailsDto);
                    });
                }

            });
        }

        //乘客事务主表
        List<SwStInputPassengerWork> passengerWorks = swStInputPassengerWorkService.list(new QueryWrapper<SwStInputPassengerWork>().lambda()
                .eq(SwStInputPassengerWork::getWorkDate, settleTime)
                .eq(SwStInputPassengerWork::getLineCode, lineCode)
                .eq(SwStInputPassengerWork::getStationCode, stationCode)
                .eq(SwStInputPassengerWork::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStInputPassengerWork::getDelFlag,"0"));

        R<List<SysDictItem>> failureOperatorData = systemUserService.getDictByType(StmConstans.STM_FAILURE_OPERATOR);
        List<SysDictItem> dictData1 = failureOperatorData.getData();
        Map<String, String> map1 = dictData1.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SysDictItem>> payData = systemUserService.getDictByType(StmConstans.PAY_WORK_EVENT_TYPE);
        List<SysDictItem> dictData2 = payData.getData();
        Map<String, String> map2 = dictData2.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SysDictItem>> cashDetailData = systemUserService.getDictByType(StmConstans.CASH_WORK_EVENT_DETAIL);
        List<SysDictItem> dictData3 = cashDetailData.getData();
        Map<String, String> map3 = dictData3.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SysDictItem>> eleDetailData = systemUserService.getDictByType(StmConstans.ELE_WORK_EVENT_DETAIL);
        List<SysDictItem> dictData4 = eleDetailData.getData();
        Map<String, String> map4 = dictData4.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        List<SwStInputPassengerWorkRefund> refundList = new ArrayList<>();
        List<SwStInputPassengerWorkPay> payList = new ArrayList<>();
        List<SwStInputPassengerWorkCash> cashList = new ArrayList<>();
        List<SwStInputPassengerWorkElectron> electronList = new ArrayList<>();
        List<SwStInputPassengerWorkSpecial> specialList = new ArrayList<>();
        List<SwStInputPassengerWorkFree> freeList = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(passengerWorks)){
            passengerWorks.forEach(x -> {
                //第四部分 乘客事务信息-故障退款
                List<SwStInputPassengerWorkRefund> refunds = swStInputPassengerWorkRefundService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkRefund>lambdaQuery()
                                .eq(SwStInputPassengerWorkRefund::getRelationId, x.getId())
                );
                if(CollectionUtil.isNotEmpty(refunds)){
                    refunds.forEach(refund -> {
                        refund.setId(i3.incrementAndGet());
                        refund.setFailureOperator(map1.get(refund.getFailureOperator()));
                        refund.setWorkTimes(DateUtilStm.LocalDateTimeToString(refund.getWorkTime()));
                        refund.setConductorName(x.getConductorName());
                    });
                    refundList.addAll(refunds);
                }

                //第五部分 乘客事务信息-付费出站发售
                List<SwStInputPassengerWorkPay> pays = swStInputPassengerWorkPayService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkPay>lambdaQuery()
                                .eq(SwStInputPassengerWorkPay::getRelationId, x.getId())
                );
                if(CollectionUtil.isNotEmpty(pays)){
                    pays.forEach(pay -> {
                        pay.setId(i4.incrementAndGet());
                        pay.setEventDetail(map2.get(pay.getEventDetail()));
                        pay.setWorkTimes(DateUtilStm.LocalDateTimeToString(pay.getWorkTime()));
                        pay.setConductorName(x.getConductorName());
                    });
                    payList.addAll(pays);
                }

                //第六部分 乘客事务信息-现金事务
                List<SwStInputPassengerWorkCash> cashes = swStInputPassengerWorkCashService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkCash>lambdaQuery()
                                .eq(SwStInputPassengerWorkCash::getRelationId, x.getId())
                );
                if(CollectionUtil.isNotEmpty(cashes)){
                    cashes.forEach(cash -> {
                        cash.setId(i5.incrementAndGet());
                        cash.setEventDetail(map3.get(cash.getEventDetail()));
                        cash.setWorkTimes(DateUtilStm.LocalDateTimeToString(cash.getWorkTime()));
                        cash.setConductorName(x.getConductorName());
                    });
                    cashList.addAll(cashes);
                }

                //第七部分 乘客事务信息-电子事务
                List<SwStInputPassengerWorkElectron> electrons = swStInputPassengerWorkElectronService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkElectron>lambdaQuery()
                                .eq(SwStInputPassengerWorkElectron::getRelationId, x.getId())
                );
                if(CollectionUtil.isNotEmpty(electrons)){
                    electrons.forEach(electron -> {
                        electron.setId(i6.incrementAndGet());
                        electron.setEventDetail(map4.get(electron.getEventDetail()));
                        electron.setWorkTimes(DateUtilStm.LocalDateTimeToString(electron.getWorkTime()));
                        electron.setConductorName(x.getConductorName());
                    });
                    electronList.addAll(electrons);
                }

                //第八部分 乘客事务信息-特殊车票发售
                List<SwStInputPassengerWorkSpecial> special = swStInputPassengerWorkSpecialService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkSpecial>lambdaQuery()
                                .eq(SwStInputPassengerWorkSpecial::getRelationId, x.getId())
                );
                if(ObjectUtil.isNotEmpty(special)){
                    special.get(0).setId(i7.incrementAndGet());
                    special.get(0).setConductorName(x.getConductorName());
                    specialList.add(special.get(0));
                }

                //第九部分 乘客事务信息-免费出站发售
                List<SwStInputPassengerWorkFree> free = swStInputPassengerWorkFreeService.getBaseMapper().selectList(
                        Wrappers.<SwStInputPassengerWorkFree>lambdaQuery()
                                .eq(SwStInputPassengerWorkFree::getRelationId, x.getId())
                );
                if(CollectionUtil.isNotEmpty(free)){
                    free.get(0).setId(i8.incrementAndGet());
                    free.get(0).setConductorName(x.getConductorName());
                    freeList.add(free.get(0));
                }
            });
        }

        //营销车票主表
        List<SwStMarketingTicket> marketingTickets = swStMarketingTicketService.list(Wrappers.<SwStMarketingTicket>lambdaQuery()
                .eq(SwStMarketingTicket::getLineCode, lineCode)
                .eq(SwStMarketingTicket::getStationCode, stationCode)
                .eq(SwStMarketingTicket::getConfirmStatus, CommonConstants.CONFIRM)
                .eq(SwStMarketingTicket::getOpertorTime, settleTime)
                .eq(SwStMarketingTicket::getDelFlag, "0"));

        R<List<SysDictItem>> takeTicketData = systemUserService.getDictByType(StmConstans.TAKE_TICKET_TYPE);
        List<SysDictItem> dictData5 = takeTicketData.getData();
        Map<String, String> map5 = dictData5.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SysDictItem>> payTypeData = systemUserService.getDictByType(StmConstans.PAY_TYPE);
        List<SysDictItem> dictData6 = payTypeData.getData();
        Map<String, String> map6 = dictData6.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));


        List<SwStMarketingTicketOffineTakeTicket> takeTicketList = new ArrayList<>();
        List<SwStMarketingTicketGroupSell> groupSellList = new ArrayList<>();

        if(CollectionUtil.isNotEmpty(marketingTickets)){
            marketingTickets.forEach(x -> {
                //第十部分 营销车票线下取票
                List<SwStMarketingTicketOffineTakeTicket> takeTickets = takeTicketService.getBaseMapper().selectList(
                        Wrappers.<SwStMarketingTicketOffineTakeTicket>lambdaQuery()
                                .eq(SwStMarketingTicketOffineTakeTicket::getRelationId, x.getId())
                                .eq(SwStMarketingTicketOffineTakeTicket::getDelFlag,"0")
                );
                if(CollectionUtil.isNotEmpty(takeTickets)){
                    takeTickets.forEach(takeTicket -> {
                        takeTicket.setId(i9.incrementAndGet());
                        takeTicket.setTicketName(ticketMap.get(takeTicket.getTicketName()));
                        takeTicket.setTakeTicketWay(map5.get(takeTicket.getTakeTicketWay()));
                        takeTicket.setConductorName(x.getConductorName());
                    });
                    takeTicketList.addAll(takeTickets);
                }

                //第十一部分 营销车票团购售卖
                List<SwStMarketingTicketGroupSell> groupSells = ticketGroupSellService.getBaseMapper().selectList(
                        Wrappers.<SwStMarketingTicketGroupSell>lambdaQuery()
                                .eq(SwStMarketingTicketGroupSell::getRelationId, x.getId())
                                .eq(SwStMarketingTicketGroupSell::getDelFlag,"0")
                );
                if(CollectionUtil.isNotEmpty(groupSells)){
                    groupSells.forEach(groupSell -> {
                        groupSell.setId(i10.incrementAndGet());
                        groupSell.setTicketName(ticketMap.get(groupSell.getTicketName()));
                        groupSell.setPayMethod(map6.get(groupSell.getPayMethod()));
                        groupSell.setConductorName(x.getConductorName());
                    });
                    groupSellList.addAll(groupSells);
                }
            });
        }

        //第十二部分 乘客事务信息-其他相关数据录入
        List<SwStInputPassengerWorkOther> workOtherList = swStInputPassengerWorkOtherService.list(new QueryWrapper<SwStInputPassengerWorkOther>()
                .eq("DATE_FORMAT(INPUT_TIME, '%Y-%m-%d')",settleTime)
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));

        R<List<SysDictItem>> failureData = systemUserService.getDictByType(StmConstans.WORK_OTHER_FAILURE_OPERATOR);
        List<SysDictItem> dictData7 = failureData.getData();
        Map<String, String> map7 = dictData7.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));
        Map<String, String> map8 = dictData7.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SwPmWorkotherDataTypeDTO>> otherData = supportService.getDictByType();
        List<SwPmWorkotherDataTypeDTO> dictData8 = otherData.getData();
        Map<String, String> map9 = dictData8.stream().collect(Collectors.toMap(SwPmWorkotherDataTypeDTO::getMainDataValue, SwPmWorkotherDataTypeDTO::getMainName));

        R<List<SwPmWorkotherHappenCauseDTO>> causeData = supportService.getParamByMainType();
        List<SwPmWorkotherHappenCauseDTO> dictData9 = causeData.getData();
        Map<String, String> map10 = dictData9.stream().collect(Collectors.toMap(SwPmWorkotherHappenCauseDTO::getSubDataValue, SwPmWorkotherHappenCauseDTO::getSubName));

        if(CollectionUtil.isNotEmpty(workOtherList)){
            workOtherList.forEach(x -> {
                x.setId(i11.incrementAndGet());
                x.setClassNumber(mapShifts.get(x.getClassNumber()));
                x.setFailureOperator(map7.get(x.getFailureOperator()));
                x.setSellOperator(map8.get(x.getSellOperator()));
                x.setDataType(map9.get(x.getDataType()));
                x.setHappenCause(map10.get(x.getHappenCause()));
            });
        }

        //第十三部分 乘客事务信息-乘客事务退换票
        List<SwStInputPassengerWorkTicket> workTicketList = swStInputPassengerWorkTicketService.list(new QueryWrapper<SwStInputPassengerWorkTicket>()
                .eq("DATE_FORMAT(HANDLE_TIME, '%Y-%m-%d')",settleTime)
                .eq("LINE_CODE", lineCode)
                .eq("STATION_CODE", stationCode)
                .eq("CONFIRM_STATUS", CommonConstants.CONFIRM)
                .eq("DEL_FLAG","0"));

        R<List<SysDictItem>> operationData = systemUserService.getDictByType(StmConstans.WORK_TICKET_OPERATION_TYPE);
        List<SysDictItem> dictData10 = operationData.getData();
        Map<String, String> map11 = dictData10.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        R<List<SysDictItem>> handleData = systemUserService.getDictByType(StmConstans.WORK_TICKET_HANDLE_TYPE);
        List<SysDictItem> dictData11 = handleData.getData();
        Map<String, String> map12 = dictData11.stream().collect(Collectors.toMap(SysDictItem::getValue, SysDictItem::getLabel));

        if(CollectionUtil.isNotEmpty(workTicketList)){
            workTicketList.forEach(x -> {
                x.setId(i12.incrementAndGet());
                x.setClassNumber(mapShifts.get(x.getClassNumber()));
                x.setOperationType(map11.get(x.getOperationType()));
                x.setHandleType(map12.get(x.getHandleType()));
                ticketMapList.forEach(map -> {
                    if(map.get("SUB_EN_NAME").equals(x.getTicketName()) && map.get("MAIN_EN_NAME").equals(x.getTicketType())){
                        x.setTicketName(map.get("SUB_NAME"));
                        x.setTicketType(map.get("MAIN_NAME"));
                    }
                });
            });
        }


        if(CollectionUtil.isNotEmpty(settleList)){
            InputStream excelTemplateIs = null;
            try {
                response.reset(); // 非常重要
                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");
                final String fileName = URLEncoder.encode("售票员BOM录入信息表", "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");

                // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
                // {} 代表普通变量 {.} 代表是list的变量

                excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/template/export/SwStConductorSettleExcelTemplate.xlsx");

                ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
                WriteSheet writeSheet = EasyExcel.writerSheet("售票员BOM录入信息表").build();
                // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
                // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
                // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
                // 如果数据量大 list不是最后一行 参照另一个
                // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 a，然后多个list必须用 FillWrapper包裹
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter.fill(new FillWrapper("a", settleList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("b", pettyAddList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("c", refundList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("d", payList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("e", cashList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("f", electronList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("g", specialList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("h", freeList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("i", takeTicketList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("j", groupSellList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("k", workOtherList), fillConfig, writeSheet);
                excelWriter.fill(new FillWrapper("l", workTicketList), fillConfig, writeSheet);
                Map<String, Object> map = new HashMap<>();
                map.put("lineName",lineName);
                map.put("stationName",stationName);
                map.put("settleTime",settleTime);
                excelWriter.fill(map, writeSheet);

                excelWriter.finish();

            } catch (Exception e) {
                e.printStackTrace();
                log.error("导出售票员BOM录入信息表错误");
            } finally {
                if(excelTemplateIs != null){
                    try {
                        excelTemplateIs.close();
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }

                }
            }
        }

    }

    private String getExportLineName (List<Map<String,String>> stationMap,String lineCode) {

        for (Map<String,String> map : stationMap) {
            if(lineCode.equals(map.get("LINE_CODE"))) {
                return map.get("LINE_NAME");
            }
        }
        return "";
    }
    private String getExportStationName (List<Map<String,String>> stationMap,String stationCode,String lineCode) {

        for (Map<String,String> map : stationMap) {
            if(stationCode.equals(map.get("STATION_CODE")) && lineCode.equals(map.get("LINE_CODE"))) {
                return map.get("STATION_NAME");
            }
        }
        return "";
    }

    /**
     * 营销车票存在处理
     * @param swStMarketingTicket
     * @param pettyAddDetails
     * @throws SQLException
     */
    public void marketingTicketExistenceProcessing(SwStMarketingTicket swStMarketingTicket, List<SwStTicketPettyAddDetails> pettyAddDetails){
        List<SwStMarketingTicketGroupSell> groupSellList = ticketGroupSellService.list(new QueryWrapper<SwStMarketingTicketGroupSell>().eq("RELATION_ID", swStMarketingTicket.getId()).eq("DEL_FLAG", 0));
        List<SwStMarketingTicketOffineTakeTicket> offineTakeTicketList = takeTicketService.list(new QueryWrapper<SwStMarketingTicketOffineTakeTicket>().eq("RELATION_ID", swStMarketingTicket.getId()).eq("DEL_FLAG", 0));

        boolean flagDel = false;
        int amount = 0; //营销车票合计数量
        BigDecimal money = new BigDecimal("0.00");  //营销车票合计金额
        // 先全部删除线下正常售卖子表（保障之前有删归还等未同步的数据）
        List<SwStMarketingTicketOffineSell> offineSellList = offineSellService.getBaseMapper().selectList(Wrappers.<SwStMarketingTicketOffineSell>lambdaQuery()
                .eq(SwStMarketingTicketOffineSell::getRelationId, swStMarketingTicket.getId()));
        if(CollectionUtil.isNotEmpty(offineSellList)){
            List<Integer> ids = offineSellList.stream().map(SwStMarketingTicketOffineSell::getId).collect(Collectors.toList());
            swStMarketingTicketOffineSellMapper.deleteBatchIds(ids);
        }
        if(CollectionUtil.isNotEmpty(pettyAddDetails)){
            //处理营销车票从表线下售卖添加逻辑
            List<SwStMarketingTicketOffineSell> ticketOffineSells = addTicketOffineSells(pettyAddDetails);
            //保存营销车票从表线下售卖
            if (CollectionUtil.isNotEmpty(ticketOffineSells)) {
                ticketOffineSells.forEach(x -> x.setRelationId(swStMarketingTicket.getId()));//销车票主表id
                offineSellService.saveBatch(ticketOffineSells);
            }
            //线下售卖营销车票总张数
            int cashSaleNumTotal = pettyAddDetails.stream().mapToInt(SwStTicketPettyAddDetails::getCashSaleNum).sum();
            //线下售卖营销车票总金额
            BigDecimal cashSaleAmountSum = pettyAddDetails.stream().map(SwStTicketPettyAddDetails::getCashSaleAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
            amount += cashSaleNumTotal;
            money = money.add(cashSaleAmountSum);

        }else {
            if(CollectionUtil.isEmpty(groupSellList) && CollectionUtil.isEmpty(offineTakeTicketList)){
                swStMarketingTicketService.removeById(swStMarketingTicket.getId());
                flagDel = true;
            }
        }
        if(!flagDel){
            //团购和线下取票数量和金额 合计
            List<Map<String, Object>> maps = null;
            try {
                maps = JdbcUtil.exeSqlQuery("SELECT IFNULL(SUM(tt.amount),0) amount,IFNULL(SUM(tt.money),0) money from (\n" +
                        "select ifnull(sum(sell_num),0) as amount,ifnull(sum(discount_amount),0) as money  from sw_st_marketing_ticket_group_sell where relation_id = "+swStMarketingTicket.getId()+" and del_flag='0'\n" +
                        " UNION ALL\n" +
                        "select ifnull(sum(ticket_num),0) as amount,ifnull(sum(sell_amount),0) as money  from sw_st_marketing_ticket_offine_take_ticket where relation_id = "+swStMarketingTicket.getId()+" and del_flag='0') tt");
            } catch (SQLException e) {
                e.printStackTrace();
            }
            if(maps!=null){
                BigDecimal b = new BigDecimal(String.valueOf(maps.get(0).get("amount")));
                amount += b.intValue();
                money = money.add((BigDecimal) maps.get(0).get("money"));
            }

            //更新营销车票主表总金额和总数量
            swStMarketingTicket.setTotalSellNum(amount);
            swStMarketingTicket.setTotalSellAmount(money);
            swStMarketingTicket.setConfirmStatus("1");
            swStMarketingTicketService.updateById(swStMarketingTicket);
        }
    }

    public List<SwStMarketingTicketOffineSell> addTicketOffineSells(List<SwStTicketPettyAddDetails> pettyAddDetails) {
        //线下正常售卖
        List<SwStMarketingTicketOffineSell> ticketOffineSells = new ArrayList<>();
        //保存营销车票从表
        pettyAddDetails.stream().forEach(x -> {
            SwStMarketingTicketOffineSell swStMarketingTicketOffineSell = new SwStMarketingTicketOffineSell();
            swStMarketingTicketOffineSell.setTicketName(x.getTicketType());//票种
            swStMarketingTicketOffineSell.setTicketType(x.getTicketName());//车票名称
            swStMarketingTicketOffineSell.setTicketPrice(x.getTicketValue());//单价
            swStMarketingTicketOffineSell.setCashSellNum(x.getCashSaleNum());//现金售卖张数
            swStMarketingTicketOffineSell.setCashSellAmount(x.getCashSaleAmount());//现金售卖金额
            swStMarketingTicketOffineSell.setTotalSellNum(x.getCashSaleNum());//合计张数
            swStMarketingTicketOffineSell.setTotalSellAmount(x.getCashSaleAmount());//合计金额
            swStMarketingTicketOffineSell.setSellTime(x.getCreateTime().toLocalDate());//售卖时间
            swStMarketingTicketOffineSell.setCreateTime(x.getCreateTime());//创建时间
            swStMarketingTicketOffineSell.setUpdateTime(x.getUpdateTime());//数据更新时间
            swStMarketingTicketOffineSell.setEntryUpdateJobNo(x.getEntryUpdateJobNo());//更新人工号
            swStMarketingTicketOffineSell.setEntryUpdateJobName(x.getEntryUpdateJobName());//更新人
            swStMarketingTicketOffineSell.setEntryUpdateTime(x.getEntryUpdateTime());//更新时间
            swStMarketingTicketOffineSell.setReportModifyStatus("0");//报表修改状态默认 0
            swStMarketingTicketOffineSell.setDelFlag("0");
            ticketOffineSells.add(swStMarketingTicketOffineSell);
        });
        return ticketOffineSells;
    }
}
